<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:blogger='http://schemas.google.com/blogger/2008' xmlns:georss='http://www.georss.org/georss' xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-2909062909816541374</id><updated>2024-10-05T05:01:25.259+03:00</updated><category term="3D-Coat"/><category term="AngelScript"/><category term="CouchDB"/><category term="Russian"/><category term="English"/><category term="магазинам"/><category term="C++"/><category term="Couchbase"/><title type='text'>На ладони</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://signmotion.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2909062909816541374/posts/default?redirect=false'/><link rel='alternate' type='text/html' href='http://signmotion.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/2909062909816541374/posts/default?start-index=26&amp;max-results=25&amp;redirect=false'/><author><name>Andrii</name><uri>http://www.blogger.com/profile/02715216472597824596</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjcrHHkyfsW8m8HmZZeyd2fhzwEl-shXbCxnYVY_mVq7uJpe5QET9SerP_bCPeO4YEBlXJT44IRPOcL7VtgFJsDqXwfppdES-fdokbXX0-11jdBQAyipvURKBH3N-Wh2VCye2U-W4nsp6zPgNSyi7g6gFgmmo34dH_oL_FTXf31U65BXQ/s220/Andrey-400x.png'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>40</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><blogger:adultContent>true</blogger:adultContent><entry><id>tag:blogger.com,1999:blog-2909062909816541374.post-4126898828455324074</id><published>2016-01-26T21:09:00.001+02:00</published><updated>2016-02-24T09:32:43.138+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="3D-Coat"/><category scheme="http://www.blogger.com/atom/ns#" term="AngelScript"/><category scheme="http://www.blogger.com/atom/ns#" term="Russian"/><title type='text'>Математика в скриптах Коута</title><content type='html'>&lt;div class=&quot;img-desc&quot;&gt;
&lt;img alt=&quot;fractal quaternion 3D-Coat&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg7zRI1UxFj_7Lor5GZmUHzRAbw9IxB0Vnke4MtZLC394GeoDbAljQ1jpZ82QwWl4qAY5_ayoaqJQOKEtQrZaWVAVzO26J8f1GKH-OqtvEOytHlLE4sgi05XSlpxamSocBpWUAmuTOvoegb/s1600/3dcoat-math-scripting.png&quot; /&gt;&lt;cite&gt;@&lt;a href=&quot;http://paulbourke.net/fractals/quatjulia/&quot;&gt;Paul Bourke&lt;/a&gt;&lt;/cite&gt;&lt;/div&gt;
Всё думал, как лучше показать работу с векторами, волшебными квадратами, кватернионами и углами Эйлера в &lt;a href=&quot;http://3dcoat.com/&quot; title=&quot;3DCoat&quot;&gt;3D-Coat&lt;/a&gt;... Этой цели хорошо подходит моделирование движения камеры вокруг сцены, но работа с камерой в скриптах &lt;a href=&quot;http://j.mp/coat-scripto-slides&quot; target=&quot;_blank&quot;&gt;будет позже&lt;/a&gt;, поэтому делаю простой обзор: наверняка Вы найдёте применение этой математике в своих скриптах.&lt;br /&gt;
&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
Объекты математики могут изменять себя или возвращать &lt;i&gt;изменённую&lt;/i&gt; копию. Методы, возвращающие копию объекта, заканчиваются на `&lt;code&gt;Copy&lt;/code&gt;`. Например, когда ниже написано `&lt;code&gt;normalize[Copy]()&lt;/code&gt;`, значит, класс имеет два метода:&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;normalize()&lt;/code&gt; - меняет сам объект&lt;/li&gt;
&lt;li&gt;&lt;code&gt;normalizeCopy()&lt;/code&gt; - возвращает изменённую копию&lt;/li&gt;
&lt;/ol&gt;
&lt;br /&gt;
&lt;h3&gt;Векторы &lt;a href=&quot;https://ru.wikipedia.org/wiki/%D0%A5%D0%B5%D0%B2%D0%B8%D1%81%D0%B0%D0%B9%D0%B4,_%D0%9E%D0%BB%D0%B8%D0%B2%D0%B5%D1%80&quot;&gt;Хэвисайда&lt;/a&gt;&lt;/h3&gt;&lt;br /&gt;
&lt;h3&gt;Vec3&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;c++&quot;&gt;// конструкторы
// все значения вектора равны 10.1
Vec3  a( 10.1 );
// инициализация XYZ
Vec3  b( 10.1, 20.2, -30.3 );
Vec3  c = { 10.1, 20.2, -30.3 };

// преобразование вектора в строку
auto  sa = string( a );

// проверка состояния
bool  stateN = a.normalized();
bool  stateZ = a.zero();

// получение элементов вектора
float  x = c[ 0 ];
float  y = c[ 1 ];
float  z = c[ 2 ];
// или
float  x = c.x();
float  y = c.y();
float  z = c.z();

// инициализация элементов
a[ 0, Значение ];
a[ 1, Значение ];
a[ 2, Значение ];
// или
a.x( Значение );
a.y( Значение );
a.z( Значение );

// арифметика
auto  negA = -a;
a += b;
a -= b;
a *= c;
a /= c;
a *= 77;
a /= 77;
Vec3  d = a + b;
Vec3  e = a - b;
Vec3  f = a * b;
Vec3  g = a / b;
Vec3  h = a * 77;
Vec3  i = a / 77;
Vec3  j = 77 * a;

// угол между двумя векторами
float  angle = a.angle( b );

// расстояние
float  distance = a.distance( b );

// скалярное произведение
float  dot = a.dot( b );

// длина вектора
float  length = c.length();

// модуль
c.abs();
auto  r = c.absCopy();
// # Далее эти две строки будут показываться как одна в виде:
//   c.abs[Copy]();

// обрезание вектора по длине
// здесь: &quot;не короче 10 и не длиннее 20.5&quot;
c.clamp[Copy]( 10, 20.5 );
// здесь: &quot;ровно 10&quot;
c.truncate[Copy]( 10 );

// векторное произведение
c.cross[Copy]( b );

// выбор макс / мин значения из этого вектора и предложенного
a.max[Copy]( b );
a.min[Copy]( b );

// нормализация вектора
a.normalize[Copy]();

// отражение
a.reflect[Copy]( b );

// преломление
a.refract[Copy]( b, angle );
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;Матрицы &lt;a href=&quot;https://ru.wikipedia.org/wiki/%D0%A1%D0%B8%D0%BB%D1%8C%D0%B2%D0%B5%D1%81%D1%82%D1%80,_%D0%94%D0%B6%D0%B5%D0%B9%D0%BC%D1%81_%D0%94%D0%B6%D0%BE%D0%B7%D0%B5%D1%84&quot;&gt;Сильвестра&lt;/a&gt;&lt;/h3&gt;&lt;br /&gt;
&lt;h3&gt;Mat3&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;c++&quot;&gt;// конструкторы
Mat3  a( 1, 2, 3,
         4, 5, 6,
         7, 8, 9 );
Mat3  b = { 1, 2, 3,
            4, 5, 6,
            7, 8, 9 };

// преобразования матрицы 3x3
auto  sa = Angles( a );
auto  sm = Mat4( a );
auto  sq = Quat( a );
auto  ss = string( a );

// проверка состояния
bool  stateI = a.identity();
bool  stateO = a.orthonormal();
bool  stateS = a.symmetric();
bool  stateZ = a.zero();

// получение элементов матрицы
float  e00 = a[ 0, 0 ];
float  e01 = a[ 0, 1 ];
// ...
float  e22 = a[ 2, 2 ];

// инициализация элементов
a[ 0, 0, Значение ];
a[ 0, 1, Значение ];
// ...
a[ 2, 2, Значение ];

// арифметика
auto  negA = -a;
a += b;
a -= b;
a *= c;
a *= 77;
a /= 77;
Vec3  d = a + b;
Vec3  e = a - b;
Vec3  f = a * b;
Vec3  h = a * 77;
Vec3  i = a / 77;
Vec3  j = 77 * a;

// детерминант
float  determinant = a.determinant();

// трассировка
float  trace = a.trace();

// инверсия
a.invert[Copy]();

// нормализация
a.orthonormalize[Copy]();

// транспонирование
a.transpose[Copy]();
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
&lt;h3&gt;Mat4&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;c++&quot;&gt;// конструкторы
Mat4  a( 1,  2,  3,  4,
         5,  6,  7,  8,
         9, 10, 11, 12 );
Mat4  b = { 1,  2,  3,  4,
            5,  6,  7,  8,
            9, 10, 11, 12 };

Mat3  rotation = { 0, 0, 1,
                   1, 0, 0,
                   0, 1, 0 };
Vec3  translation = { -100, -20, 50 };
Mat4  c( rotation, translation );

Vec3  scaling = { 1, 20, 300 };
Mat4  d( scaling, translation );

// преобразования матрицы 4x4
auto  sm = Mat3( a );
auto  sq = Quat( a );
auto  ss = string( a );

// проверка состояния
bool  stateI = a.identity();
bool  stateO = a.orthonormal();
bool  stateS = a.symmetric();
bool  stateZ = a.zero();

// получение элементов матрицы
float  e00 = a[ 0, 0 ];
float  e01 = a[ 0, 1 ];
// ...
float  e33 = a[ 3, 3 ];

// инициализация элементов матрицы
a[ 0, 0, Значение ];
a[ 0, 1, Значение ];
// ...
a[ 3, 3, Значение ];

// арифметика
auto  negA = -a;
a += b;
a -= b;
a *= c;
a *= 77;
a /= 77;
Vec3  d = a + b;
Vec3  e = a - b;
Vec3  f = a * b;
Vec3  h = a * 77;
Vec3  i = a / 77;
Vec3  j = 77 * a;

// детерминант
float  determinant = a.determinant();

// трассировка
float  trace = a.trace();

// инверсия
a.invert[Copy]();

// транспонирование
a.transpose[Copy]();
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;Углы &lt;a href=&quot;https://ru.wikipedia.org/wiki/%D0%AD%D0%B9%D0%BB%D0%B5%D1%80,_%D0%9B%D0%B5%D0%BE%D0%BD%D0%B0%D1%80%D0%B4&quot;&gt;Эйлера&lt;/a&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;c++&quot;&gt;// конструкторы
Angles  a( 1, 2, 3 );
Angles  b = { -1.1, 2.2, -3.3 };

// преобразования
auto  sm = Mat3( a );
auto  sn = Mat4( a );
auto  sq = Quat( a );
auto  sa = string( a );

// проверка состояния
bool  stateZ = a.zero();

// получение элементов
float  pitch = a[ 0 ];
float  yaw   = a[ 1 ];
float  roll  = a[ 2 ];
// или
float  pitch = a.pitch();
float  yaw   = a.yaw();
float  roll  = a.roll();

// инициализация элементов
a[ 0, Значение ];
a[ 1, Значение ];
a[ 2, Значение ];
// или
a.pitch( Значение );
a.yaw( Значение );
a.roll( Значение );

// арифметика
auto  negA = -a;
a += b;
a -= b;
a *= 77;
a /= 77;
Vec3  d = a + b;
Vec3  e = a - b;
Vec3  h = a * 77;
Vec3  i = a / 77;
Vec3  j = 77 * a;

// нормализация углов
a.normalize180[Copy]();
a.normalize360[Copy]();
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;Кватернионы &lt;a href=&quot;https://ru.wikipedia.org/wiki/%D0%93%D0%B0%D0%BC%D0%B8%D0%BB%D1%8C%D1%82%D0%BE%D0%BD,_%D0%A3%D0%B8%D0%BB%D1%8C%D1%8F%D0%BC_%D0%A0%D0%BE%D1%83%D1%8D%D0%BD&quot;&gt;Гамильтона&lt;/a&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;c++&quot;&gt;// конструкторы
Quat  a( 1.1, 2.2, 3.3, 50 );
Quat  b = { 1.1, 2.2, -3.3, 50 };
Quat  c = a * 10;

// преобразования кватерниона
auto  sa = Angles( a );
auto  sm = Mat3( a );
auto  sn = Mat4( a );
auto  ss = string( a );

// проверка состояния
bool  stateN = a.normalized();
bool  stateZ = a.zero();

// получение элементов
float  x = a[ 0 ];
float  y = a[ 1 ];
float  z = a[ 2 ];
float  w = a[ 3 ];
// или
float  x = a.x();
float  y = a.y();
float  z = a.z();
float  w = a.w();

// инициализация элементов
a[ 0, Значение ];
a[ 1, Значение ];
a[ 2, Значение ];
a[ 3, Значение ];
// или
a.x( Значение );
a.y( Значение );
a.z( Значение );
a.w( Значение );

// арифметика
auto  negA = -a;
a += b;
a -= b;
a *= c;
a /= c;
a *= 77;
a /= 77;
Vec3  d = a + b;
Vec3  e = a - b;
Vec3  f = a * b;
Vec3  g = a / b;
Vec3  h = a * 77;
Vec3  i = a / 77;
Vec3  j = 77 * a;

// скалярное произведение
float  dot = a.dot( b );

// длина
float  length = c.length();

// вычисление `w`
c.calcW[Copy]();

// устанавливает `w = 0` и
// меняет знак для `xyz`, если было `w &lt; 0`
a.compress[Copy]();

// сопряжение
a.conjugate[Copy]();

// степень
a.exp[Copy]();

// инверсия
a.invert[Copy]();

// логарифм
a.ln[Copy]();

// нормализация
a.normalize[Copy]();
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
Представленные выше классы соблюдают принятые для скриптинга &lt;a href=&quot;https://docs.google.com/presentation/d/1EdRWnW-tECzB1bwKUDO8zfJkrQscxHluHams4ssQRcQ/present#slide=id.ge8afddd9a_0_151&quot; target=&quot;_blank&quot;&gt;соглашения&lt;/a&gt;. А именно:&lt;br /&gt;
&lt;br /&gt;
Можно строить цепочки методов.
&lt;pre&gt;&lt;code class=&quot;c++&quot;&gt;v.abs().normalize();&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
Объекты одного класса сравниваются оператором `==`.
&lt;pre&gt;&lt;code class=&quot;c++&quot;&gt;if (a == b) ...&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
При переводе объекта в строку, получаем его состояние в формате JSON.
&lt;pre&gt;&lt;code class=&quot;c++&quot;&gt;[10.1, 20.2, -30.3]&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
Как-то незаконченно получилось... Закончу списком хороших статей, которые наглядно рассказывают о &lt;a href=&quot;http://www.3dgep.com/3d-math-primer-for-game-programmers-vector-operations/&quot;&gt;векторах&lt;/a&gt;, &lt;a href=&quot;http://www.3dgep.com/3d-math-primer-for-game-programmers-matrices/&quot;&gt;матрицах&lt;/a&gt; и &lt;a href=&quot;http://www.3dgep.com/understanding-quaternions/&quot;&gt;кватернионах&lt;/a&gt;. Где список? В этом же абзаце, см. ссылки!) И отличные видео-лекции на закуску: &lt;a href=&quot;https://youtu.be/sKCF8A3XGxQ?list=PLW3Zl3wyJwWOpdhYedlD-yCB7WQoHf-My&quot;&gt;игры&lt;/a&gt; и &lt;a href=&quot;https://youtu.be/zm9bqSSiIdo?list=PL7wAPgl1JVvUEb0dIygHzO4698tmcwLk9&quot;&gt;математика&lt;/a&gt;.
</content><link rel='replies' type='application/atom+xml' href='http://signmotion.blogspot.com/feeds/4126898828455324074/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2909062909816541374/4126898828455324074?isPopup=true' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2909062909816541374/posts/default/4126898828455324074'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2909062909816541374/posts/default/4126898828455324074'/><link rel='alternate' type='text/html' href='http://signmotion.blogspot.com/2016/01/3dcoat-script-math.html' title='Математика в скриптах Коута'/><author><name>Andrii</name><uri>http://www.blogger.com/profile/02715216472597824596</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjcrHHkyfsW8m8HmZZeyd2fhzwEl-shXbCxnYVY_mVq7uJpe5QET9SerP_bCPeO4YEBlXJT44IRPOcL7VtgFJsDqXwfppdES-fdokbXX0-11jdBQAyipvURKBH3N-Wh2VCye2U-W4nsp6zPgNSyi7g6gFgmmo34dH_oL_FTXf31U65BXQ/s220/Andrey-400x.png'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg7zRI1UxFj_7Lor5GZmUHzRAbw9IxB0Vnke4MtZLC394GeoDbAljQ1jpZ82QwWl4qAY5_ayoaqJQOKEtQrZaWVAVzO26J8f1GKH-OqtvEOytHlLE4sgi05XSlpxamSocBpWUAmuTOvoegb/s72-c/3dcoat-math-scripting.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2909062909816541374.post-3134314102043525750</id><published>2015-12-29T18:00:00.000+02:00</published><updated>2016-02-24T10:02:53.891+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="3D-Coat"/><category scheme="http://www.blogger.com/atom/ns#" term="AngelScript"/><category scheme="http://www.blogger.com/atom/ns#" term="English"/><title type='text'>3D-Coat, AngelScript, Debugging</title><content type='html'>&lt;div class=&quot;img-desc&quot;&gt;&lt;img alt=&quot;Debug, Scriping, 3D-Coat, AngelScript&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg5S4aVEEq-9QpKqsRuytgS61ZhnlTOn5I1AWqijKWPu3bR54KVJRD3YaMXmQZNlUJbFspCySFdEx1Q01D42t9kt52ftIWf88y7fJ00bUy20De-8zSy7qZ2LxRVESnzDkFzwcn9_Ov_sBBi/s1600/x-wing-function-3d-coat.png&quot; /&gt;&lt;/div&gt;
&lt;div class=&quot;read-in&quot;&gt;&lt;a href=&quot;/2015/12/3d-coat-script-debug.html&quot; title=&quot;3D-Coat, AngelScript, Отладка&quot;&gt;&amp;sect; Читать по-русски &amp;rarr;&lt;/a&gt;&lt;/div&gt;
Scripts in &lt;a href=&quot;http://3dcoat.com/&quot; title=&quot;Powerful sculpting&quot;&gt;3D-Coat&lt;/a&gt; could be complex: because they are written in AngelScript, which is a C++ like language, and &lt;a href=&quot;http://angelcode.com/angelscript/users.html&quot; target=&quot;_blank&quot; title=&quot;Scripting aka C++&quot;&gt;many&lt;/a&gt; large-scale and successful projects were written, using it. In order to help programmers, I added possibility to perform debugging, including one specific to 3D-Coat. Including the code, of course:
&lt;br /&gt;&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class=&quot;c++&quot;&gt;Debug  dbg;
// text log, menu `Scripts / View execution log`
DebugLog  log = dbg.log();
// viewport log
DebugDraw  drw = dbg.draw();
&lt;/code&gt;&lt;/pre&gt;
Add the following three line in the beginning of each script, and we have access to text log-file (`&lt;code&gt;log&lt;/code&gt;`) and graphic viewport elements (`&lt;code&gt;drw&lt;/code&gt;`) of Coat.&lt;br /&gt;
&lt;pre&gt;&lt;code class=&quot;c++&quot;&gt;void main() {

    log.clear();
    drw.clear().color( 0xFFFFEE00 );

    // ...
}&lt;/code&gt;&lt;/pre&gt;


&lt;br /&gt;
What can we type to log?&lt;br /&gt;

&lt;pre&gt;&lt;code class=&quot;c++&quot;&gt;// the concrete value of variable
float  delta = 1.2345;
log += delta;
&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;&lt;code class=&quot;c++&quot;&gt;// math result
// @see AngelScript math functions
log += pow( a, 3 ) * sqrt( 2 ) / 12;
&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;&lt;code class=&quot;c++&quot;&gt;// note
log +=
    &quot;This is a debug-note.&quot;
    &quot; We do treat variables provisionally as constants.&quot;;
&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;&lt;code class=&quot;c++&quot;&gt;// all local variables
log += dbg.vars();
// or (any longe, where more one variant, write without &quot;or&quot;)
log += dbg.variables();
&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;&lt;code class=&quot;c++&quot;&gt;// all global variables
log += dbg.gvars();
log += dbg.globalVariables();
&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;&lt;code class=&quot;c++&quot;&gt;// current callstack
log += dbg.callstack();
&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;&lt;code class=&quot;c++&quot;&gt;// mesh like text
Builder  builder;
const Mesh  a = builder.cylinder()
  .positionTop( Vec3( 0, 120, 0 ) )
  .positionBottom( Vec3( 0, 0, 0 ) )
  .radiusTop( 50 )
  .radiusBottom( 50 )
  .details( 0.1 )
  ();
log += a;
&lt;/code&gt;&lt;/pre&gt;


&lt;br /&gt;
What can we display in the viewport?&lt;br /&gt;

&lt;pre&gt;&lt;code class=&quot;c++&quot;&gt;// point( position, color )
drw.point( Vec3( 50, 0, 0 ) );
drw.point( Vec3( 50, 60, 0 ), Color( 0xFFAAFF33 ) );
&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;&lt;code class=&quot;c++&quot;&gt;// line( startPosition, endPosition, startColor, endColor )
drw.line( Vec3( 0, 0, 0 ), Vec3( 100, 50, 25 ) );
drw.line( Vec3( 0, 50, 0 ), Vec3( 0, 200, 25 ),
    Color( 0xFF33FF33 ) );
drw.line( Vec3( 100, 120, 0 ), Vec3( 100, 250, 25 ),
    Color( 0xFFAA0000 ), Color( 0xFF0000AA ) );
&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;&lt;code class=&quot;c++&quot;&gt;// circle( position, normal, radius, color )
drw.circle( Vec3( 0, 0, 0 ), Vec3( 100, 50, 25 ), 20 );
drw.circle( Vec3( 0, 50, 0 ), Vec3( 0, 200, 25 ), 50,
    Color( 0xFF55FFAA ) );
&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;&lt;code class=&quot;c++&quot;&gt;// sphere( position, radius, color )
drw.sphere( Vec3( 0, 0, 0 ), 15 );
drw.sphere( Vec3( 0, 50, 0 ), 45,
    Color( 0x9955FFAA ) );
&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;&lt;code class=&quot;c++&quot;&gt;// triangle( A, B, C, colorA, colorB, colorC )
const Vec3  a( 0, 0, 0 );
const Vec3  b( 80, 30, 70 );
const Vec3  c( 10, 25, 100 ) );
drw.triangle( a, b, c );
drw.triangle( a, b, c,
    Color( 0x77AA0000 ) );
drw.triangle( a, b, c,
    Color( 0xFFAA0000 ), Color( 0xFF00AA00 ), Color( 0xFF0000AA ) );
&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;&lt;code class=&quot;c++&quot;&gt;// note( position, text )
drw.note( Vec3( 0, 0, 0 ),  &quot;Note A&quot; );
drw.note( Vec3( 0, 30, 0 ), &quot;Note B&quot;,
    Color( 0xFF33FF33 ) );
drw.note( Vec3( 0, 0, 20 ),  111 );
drw.note( Vec3( 0, 30, 20 ), 222.51,
    Color( 0xFF33FF33 ) );
&lt;/code&gt;&lt;/pre&gt;

&lt;br /&gt;
Complex visualization can be separated to layers to show / hide them separately. This can be done easily:
&lt;pre&gt;&lt;code class=&quot;c++&quot;&gt;drw += &quot;My 1&quot;;
drw.layer( &quot;My 1&quot; );
// drawing in the layer `My 1`
// ...
drw += &quot;My 2&quot;;
// drawing in the layer `My 2`
// ...
&lt;/code&gt;&lt;/pre&gt;

&lt;br /&gt;
Vectors, matrix, boxes (know &lt;a href=&quot;http://gamedev.ru/terms/AABB&quot;&gt;what is AABB&lt;/a&gt;?), etc. won&#39;t be here: obviously, typing / visualization are simple:
&lt;pre&gt;&lt;code class=&quot;c++&quot;&gt;log += MyObject;
drw += MyObjectWhichCanBeDraw;
&lt;/code&gt;&lt;/pre&gt;

&lt;br /&gt;
Lastly, a smallest example of using &lt;a href=&quot;http://3dcoat.com/&quot; title=&quot;Tools for represent your 3D-ideas&quot;&gt;3D-Coat&lt;/a&gt;&#39;s possibilities for quick 3D-visualization.
&lt;pre&gt;&lt;code class=&quot;c++&quot;&gt;Debug  dbg;
DebugDraw  drw = dbg.draw();

void main() {

    drw.clear().color( 0xFFFFEE00 );
    Step( 1 );

    // parameter function
    const float  S = 10;
    const float  D = 180 * 4;
    const float  step = 0.5;
    for ( float t = -D; t &lt;= D; t += step ) {
        const float  angle = t * 3.14 / 180;
        const float  x = t * sin( angle ) * sin( angle );
        const float  y = x * cos( angle );
        const float  z = y * cos( angle ) * cos( angle );
        const Vec3  p( x, y, z );
        drw.vector( p * S, p * S / 2,
            Color( 0xFF000000 ), Color( 0xFF1100BB ) );
        drw.sphere( p * S, 100, Color( 0xFFFFEE00 ) );
        // the script working too fast) push a pause
        if ( ceil( x * y * z * S ) % 5 == 0 ) {
            Step( 1 );
        }
    } // for ...
}&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Result&lt;/h3&gt;
&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhl6VvLwMdenEYlC7oaODxIUcaNgT9DjlnK49JJo75RSre27D3xCTFwEMiIWLypzFNvpVT6KSlmDFb9Bsqped_7TeAC_w7QBX5TOYo0MaVV007kNepPWtiMlf81-ilxX-br24S4EwGNIZPq/s1600/3d-coat-function-scripting.png&quot; /&gt;

&lt;br /&gt;&lt;iframe width=&quot;619&quot; height=&quot;348&quot; src=&quot;https://www.youtube.com/embed/qYeR64J9unE&quot; frameborder=&quot;0&quot; allowfullscreen&gt;&lt;/iframe&gt;

&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://signmotion.blogspot.com/feeds/3134314102043525750/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2909062909816541374/3134314102043525750?isPopup=true' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2909062909816541374/posts/default/3134314102043525750'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2909062909816541374/posts/default/3134314102043525750'/><link rel='alternate' type='text/html' href='http://signmotion.blogspot.com/2015/12/3d-coat-script-debug-en.html' title='3D-Coat, AngelScript, Debugging'/><author><name>Andrii</name><uri>http://www.blogger.com/profile/02715216472597824596</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjcrHHkyfsW8m8HmZZeyd2fhzwEl-shXbCxnYVY_mVq7uJpe5QET9SerP_bCPeO4YEBlXJT44IRPOcL7VtgFJsDqXwfppdES-fdokbXX0-11jdBQAyipvURKBH3N-Wh2VCye2U-W4nsp6zPgNSyi7g6gFgmmo34dH_oL_FTXf31U65BXQ/s220/Andrey-400x.png'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg5S4aVEEq-9QpKqsRuytgS61ZhnlTOn5I1AWqijKWPu3bR54KVJRD3YaMXmQZNlUJbFspCySFdEx1Q01D42t9kt52ftIWf88y7fJ00bUy20De-8zSy7qZ2LxRVESnzDkFzwcn9_Ov_sBBi/s72-c/x-wing-function-3d-coat.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2909062909816541374.post-8275392752943104164</id><published>2015-12-29T15:52:00.002+02:00</published><updated>2016-02-24T09:55:48.334+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="3D-Coat"/><category scheme="http://www.blogger.com/atom/ns#" term="AngelScript"/><category scheme="http://www.blogger.com/atom/ns#" term="Russian"/><title type='text'>3D-Coat, AngelScript, отладка</title><content type='html'>&lt;div class=&quot;img-desc&quot;&gt;&lt;img alt=&quot;Debug, Scriping, 3D-Coat, AngelScript&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg5S4aVEEq-9QpKqsRuytgS61ZhnlTOn5I1AWqijKWPu3bR54KVJRD3YaMXmQZNlUJbFspCySFdEx1Q01D42t9kt52ftIWf88y7fJ00bUy20De-8zSy7qZ2LxRVESnzDkFzwcn9_Ov_sBBi/s1600/x-wing-function-3d-coat.png&quot; /&gt;&lt;/div&gt;
&lt;div class=&quot;read-in&quot;&gt;&lt;a href=&quot;/2015/12/3d-coat-script-debug-en.html&quot; title=&quot;3D-Coat, AngelScript, Debugging&quot;&gt;&amp;sect; Read in English &amp;rarr;&lt;/a&gt;&lt;/div&gt;
Скрипты в &lt;a href=&quot;http://3dcoat.com/&quot; title=&quot;Мощный скульптинг и текстурирование&quot;&gt;3D-Coat&lt;/a&gt; могут быть сложными: ведь они пишутся на AngelScript, а с этим языком уже связано довольно &lt;a href=&quot;http://angelcode.com/angelscript/users.html&quot; title=&quot;Скриптинг аля C++&quot; target=&quot;_blank&quot;&gt;много&lt;/a&gt; больших и успешных проектов. Чтобы помочь программистам, добавил некоторые возможности отладки, включая специфичные для 3D-приложений. По традиции, сразу код:
&lt;br /&gt;&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class=&quot;c++&quot;&gt;Debug  dbg;
// текстовый лог, меню `Скрипты / Посмотреть журнал выполнения`
DebugLog  log = dbg.log();
// вьюпорт, графика
DebugDraw  drw = dbg.draw();
&lt;/code&gt;&lt;/pre&gt;
Эти три строки включаем в начало своих скриптов - и получаем доступ к текстовому лог-файлу (`&lt;code&gt;log&lt;/code&gt;`) и графическому вьюпорту (`&lt;code&gt;drw&lt;/code&gt;`) Коута.&lt;br /&gt;
&lt;pre&gt;&lt;code class=&quot;c++&quot;&gt;void main() {

    // подготавливаем текстовый лог
    log.clear();
    // подготавливаем вьюпорт
    //   1) очищаем
    //   2) выбираем цвет кисти по умолчанию
    drw.clear().color( 0xFFFFEE00 );

    // дальше - что хотим показать / отобразить
    // ...
}&lt;/code&gt;&lt;/pre&gt;


&lt;br /&gt;
Что можем напечатать в лог?&lt;br /&gt;

&lt;pre&gt;&lt;code class=&quot;c++&quot;&gt;// значения конкретных переменных
float  delta = 1.2345;
log += delta;
&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;&lt;code class=&quot;c++&quot;&gt;// результаты математических операций
// @see AngelScript math functions
log += pow( a, 3 ) * sqrt( 2 ) / 12;
&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;&lt;code class=&quot;c++&quot;&gt;// текст / заметку
log +=
    &quot;This is a debug-note.&quot;
    &quot; We do treat variables provisionally as constants.&quot;;
&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;&lt;code class=&quot;c++&quot;&gt;// все объявленные локальные переменные
log += dbg.vars();
// или (дальше, когда неск. вариантов, пишу без &quot;или&quot;)
log += dbg.variables();
&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;&lt;code class=&quot;c++&quot;&gt;// все объявленные глобальные переменные
log += dbg.gvars();
log += dbg.globalVariables();
&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;&lt;code class=&quot;c++&quot;&gt;// текущий стек вызовов
log += dbg.callstack();
&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;&lt;code class=&quot;c++&quot;&gt;// меш
// да, структура меша появится в виде текста
// исключительно для осознанных жителей &quot;Матрицы&quot;)
Builder  builder;
const Mesh  a = builder.cylinder()
  .positionTop( Vec3( 0, 120, 0 ) )
  .positionBottom( Vec3( 0, 0, 0 ) )
  .radiusTop( 50 )
  .radiusBottom( 50 )
  .details( 0.1 )
  ();
log += a;
&lt;/code&gt;&lt;/pre&gt;


&lt;br /&gt;
Что можем отобразить во вьюпорт?&lt;br /&gt;

&lt;pre&gt;&lt;code class=&quot;c++&quot;&gt;// точку
// point( position, color )
drw.point( Vec3( 50, 0, 0 ) );
drw.point( Vec3( 50, 60, 0 ), Color( 0xFFAAFF33 ) );
&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;&lt;code class=&quot;c++&quot;&gt;// линию
// line( startPosition, endPosition, startColor, endColor )
drw.line( Vec3( 0, 0, 0 ), Vec3( 100, 50, 25 ) );
drw.line( Vec3( 0, 50, 0 ), Vec3( 0, 200, 25 ),
    Color( 0xFF33FF33 ) );
drw.line( Vec3( 100, 120, 0 ), Vec3( 100, 250, 25 ),
    Color( 0xFFAA0000 ), Color( 0xFF0000AA ) );
&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;&lt;code class=&quot;c++&quot;&gt;// круг
// circle( position, normal, radius, color )
drw.circle( Vec3( 0, 0, 0 ), Vec3( 100, 50, 25 ), 20 );
drw.circle( Vec3( 0, 50, 0 ), Vec3( 0, 200, 25 ), 50,
    Color( 0xFF55FFAA ) );
&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;&lt;code class=&quot;c++&quot;&gt;// сферу
// sphere( position, radius, color )
drw.sphere( Vec3( 0, 0, 0 ), 15 );
drw.sphere( Vec3( 0, 50, 0 ), 45,
    Color( 0x9955FFAA ) );
&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;&lt;code class=&quot;c++&quot;&gt;// треугольник
// triangle( A, B, C, colorA, colorB, colorC )
const Vec3  a( 0, 0, 0 );
const Vec3  b( 80, 30, 70 );
const Vec3  c( 10, 25, 100 ) );
drw.triangle( a, b, c );
drw.triangle( a, b, c,
    Color( 0x77AA0000 ) );
drw.triangle( a, b, c,
    Color( 0xFFAA0000 ), Color( 0xFF00AA00 ), Color( 0xFF0000AA ) );
&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;&lt;code class=&quot;c++&quot;&gt;// надпись, число
// note( position, text )
drw.note( Vec3( 0, 0, 0 ),  &quot;Note A&quot; );
drw.note( Vec3( 0, 30, 0 ), &quot;Note B&quot;,
    Color( 0xFF33FF33 ) );
drw.note( Vec3( 0, 0, 20 ),  111 );
drw.note( Vec3( 0, 30, 20 ), 222.51,
    Color( 0xFF33FF33 ) );
&lt;/code&gt;&lt;/pre&gt;

&lt;br /&gt;
Сложную визуализацию можно разбросать по слоям, чтобы отображать / скрывать их по отдельности. Делается просто:
&lt;pre&gt;&lt;code class=&quot;c++&quot;&gt;drw += &quot;My 1&quot;;
drw.layer( &quot;My 1&quot; );
// теперь всё рисуется в слое `My 1`
// ...
drw += &quot;My 2&quot;;
// а теперь - в слое `My 2`
// ...
&lt;/code&gt;&lt;/pre&gt;

&lt;br /&gt;
Векторы, матрицы, боксы (ведь знаете, &lt;a href=&quot;http://gamedev.ru/terms/AABB&quot;&gt;что такое AABB&lt;/a&gt;?) и пр. здесь не перечисляю: очевидно, что они печатаются / визуализируются просто:
&lt;pre&gt;&lt;code class=&quot;c++&quot;&gt;log += МойОбъект;
drw += МойОбъектКоторыйМожноНарисовать;
&lt;/code&gt;&lt;/pre&gt;

&lt;br /&gt;
Напоследок, малюсенький пример, как использовать возможности &lt;a href=&quot;http://3dcoat.com/&quot; title=&quot;Как воплотить свою 3D-идею?&quot;&gt;Коута&lt;/a&gt; для &lt;i&gt;быстрой&lt;/i&gt; 3D-визуализации.
&lt;pre&gt;&lt;code class=&quot;c++&quot;&gt;Debug  dbg;
DebugDraw  drw = dbg.draw();

void main() {

    drw.clear().color( 0xFFFFEE00 );
    Step( 1 );

    // параметрическая функция
    const float  S = 10;
    const float  D = 180 * 4;
    const float  step = 0.5;
    for ( float t = -D; t &lt;= D; t += step ) {
        const float  angle = t * 3.14 / 180;
        const float  x = t * sin( angle ) * sin( angle );
        const float  y = x * cos( angle );
        const float  z = y * cos( angle ) * cos( angle );
        const Vec3  p( x, y, z );
        drw.vector( p * S, p * S / 2,
            Color( 0xFF000000 ), Color( 0xFF1100BB ) );
        drw.sphere( p * S, 100, Color( 0xFFFFEE00 ) );
        // скрипт работает слишком быстро) замедляем
        if ( ceil( x * y * z * S ) % 5 == 0 ) {
            Step( 1 );
        }
    } // for ...
}&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Результат&lt;/h3&gt;
&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhl6VvLwMdenEYlC7oaODxIUcaNgT9DjlnK49JJo75RSre27D3xCTFwEMiIWLypzFNvpVT6KSlmDFb9Bsqped_7TeAC_w7QBX5TOYo0MaVV007kNepPWtiMlf81-ilxX-br24S4EwGNIZPq/s1600/3d-coat-function-scripting.png&quot; /&gt;

&lt;br /&gt;&lt;iframe width=&quot;619&quot; height=&quot;348&quot; src=&quot;https://www.youtube.com/embed/qYeR64J9unE&quot; frameborder=&quot;0&quot; allowfullscreen&gt;&lt;/iframe&gt;

&lt;br /&gt;
</content><link rel='replies' type='application/atom+xml' href='http://signmotion.blogspot.com/feeds/8275392752943104164/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2909062909816541374/8275392752943104164?isPopup=true' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2909062909816541374/posts/default/8275392752943104164'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2909062909816541374/posts/default/8275392752943104164'/><link rel='alternate' type='text/html' href='http://signmotion.blogspot.com/2015/12/3d-coat-script-debug.html' title='3D-Coat, AngelScript, отладка'/><author><name>Andrii</name><uri>http://www.blogger.com/profile/02715216472597824596</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjcrHHkyfsW8m8HmZZeyd2fhzwEl-shXbCxnYVY_mVq7uJpe5QET9SerP_bCPeO4YEBlXJT44IRPOcL7VtgFJsDqXwfppdES-fdokbXX0-11jdBQAyipvURKBH3N-Wh2VCye2U-W4nsp6zPgNSyi7g6gFgmmo34dH_oL_FTXf31U65BXQ/s220/Andrey-400x.png'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg5S4aVEEq-9QpKqsRuytgS61ZhnlTOn5I1AWqijKWPu3bR54KVJRD3YaMXmQZNlUJbFspCySFdEx1Q01D42t9kt52ftIWf88y7fJ00bUy20De-8zSy7qZ2LxRVESnzDkFzwcn9_Ov_sBBi/s72-c/x-wing-function-3d-coat.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2909062909816541374.post-7947087577685095133</id><published>2015-12-14T18:00:00.000+02:00</published><updated>2016-03-22T14:49:55.376+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="3D-Coat"/><category scheme="http://www.blogger.com/atom/ns#" term="AngelScript"/><category scheme="http://www.blogger.com/atom/ns#" term="English"/><title type='text'>Primitives and Scripting: what you can do already</title><content type='html'>&lt;div class=&quot;img-desc&quot;&gt;&lt;img alt=&quot;Primitives, boolean operations, 3D-Coat, AngelScript&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhyWcFFwKnt_iCmp0WuMLlpTTw7t3f0Ue2zUpoFF6cS85zJNCDS9shg2jN0WObPHkjeuzePuJ9T5RTpM-dVhMIHNCNTYYzcd6xgZNvgcFGScD4xkyEPpORnI8hLHjq4SY1eG8FwuiunXnlH/s1600/primitives-boolean-scripting-3d-coat.png&quot; /&gt;&lt;/div&gt;
&lt;div class=&quot;read-in&quot;&gt;&lt;a href=&quot;/2015/12/primitives-scripting-3dcoat.html&quot; title=&quot;Примитивы и скриптинг: что уже можно&quot;&gt;&amp;sect; Читать по-русски &amp;rarr;&lt;/a&gt;&lt;/div&gt;
Basic set of primitives have been added. Now you can create them via scripts in &lt;a href=&quot;http://3dcoat.com/learn/&quot; title=&quot;Learn Coat, video&quot;&gt;3D-Coat&lt;/a&gt;. Moreover, you can perform some actions with them: change location, scale. That may not be much, but the foundation is laid, and new scripting approach is easier, hopefully, for mastering (old possibilities &lt;a href=&quot;http://j.mp/3dc-angelscript&quot; title=&quot;Documentation for scripting&quot;&gt;remained&lt;/a&gt; – previously written scripts will work too). New scripts will be available as of version &lt;a href=&quot;http://3d-coat.com/forum/index.php?showtopic=17076&quot; title=&quot;Download a fresh version&quot;&gt;4.5.26&lt;/a&gt;.
&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;Code:
&lt;br /&gt;
&lt;pre&gt;&lt;code class=&quot;c++&quot;&gt;const Vec3  TOWER_SHIFT( 0, 0, 200 );
const Vec3  FLOOR_SHIFT( 0, 200, 0 );
Vec3  tower = TOWER_SHIFT * (-4.5);
Vec3  floor( 0 );
Mesh  a, b, mesh;
Builder  builder;
SculptRoom  room;


void main() {

    room.clear().toSurface();

    // capsule
    {
        a = builder.capsule()
          .startPosition( Vec3( 0 ) )
          .endPosition( Vec3( 40, 50, 60 ) )
          .startRadius( 30 )
          .endRadius( 50 )
          .details( 0.1 )
          .build();
        b = builder.capsule()
          .startPosition( Vec3( 0 ) )
          .endPosition( Vec3( 20, 30, 40 ) )
          .startRadius( 20 )
          .endRadius( 30 )
          .position( Vec3( 20, 30, 40 ) )
          .details( 0.5 )
          .build();
        draw();
    }

    // cone
    {
        a = builder.cone()
          .radius( 50 )
          .height( 120 )
          .details( 0.1 )
          .build();
        b = builder.cone()
          .radius( 40 )
          .height( 80 )
          .position( Vec3( 10, 20, 30 ) )
          .details( 0.5 )
          .build();
        draw();
    }

    // cuboid
    {
        a = builder.cuboid()
          .side( Vec3( 100, 80, 60 ) )
          .details( 0.1 )
          .build();
        b = builder.cuboid()
          .side( Vec3( 30, 50, 70 ) )
          .position( Vec3( 20, 30, 40 ) )
          .details( 0.5 )
          .build();
        draw();
    }

    // cylinder
    {
        a = builder.cylinder()
          .positionTop( Vec3( 80, 0, 0 ) )
          .positionBottom( Vec3( 0, 0, 0 ) )
          .radiusTop( 40 )
          .radiusBottom( 50 )
          .details( 0.1 )
          .build();
        b = builder.cylinder()
          .positionTop( Vec3( 70, 0, 10 ) )
          .positionBottom( Vec3( 0, 0, 0 ) )
          .radiusTop( 20 )
          .radiusBottom( 30 )
          .position( Vec3( 20, 30, 40 ) )
          .details( 0.5 )
          .build();
        draw();
    }

    // ellipsoid
    {
        a = builder.ellipsoid()
          .radius( Vec3( 80, 60, 40 ) )
          .details( 0.1 )
          .build();
        b = builder.ellipsoid()
          .radius( Vec3( 20, 40, 60 ) )
          .position( Vec3( 20, 30, 40 ) )
          .details( 0.5 )
          .build();
        draw();
    }

    // gear
    {
        a = builder.gear()
          .startPoint( Vec3( 0, 0, 0 ) )
          .endPoint( Vec3( 90, 90, 90 ) )
          .topRadius( 30 )
          .bottomRadius( 50 )
          .relativeHoleRadius( 0.3 )
          .depth( 0.5 )
          .sharpness( 0.2 )
          .teeth( 3 )
          .details( 0.1 )
          .build();
        b = builder.gear()
          .startPoint( Vec3( 20, 20, 20 ) )
          .endPoint( Vec3( 50, 50, 50 ) )
          .topRadius( 50 )
          .bottomRadius( 50 )
          .relativeHoleRadius( 0.3 )
          .depth( 0.2 )
          .sharpness( 1.0 )
          .teeth( 6 )
          .details( 0.5 )
          .build();
        draw();
    }

    // ngon
    {
        a = builder.ngon()
          .startPoint( Vec3( 0, 0, 0 ) )
          .endPoint( Vec3( 90, 90, 90 ) )
          .topRadius( 30 )
          .bottomRadius( 40 )
          .relativeHoleRadius( 0.3 )
          .teeth( 3 )
          .details( 0.1 )
          .build();
        b = builder.ngon()
          .startPoint( Vec3( 20, 20, 20 ) )
          .endPoint( Vec3( 50, 50, 50 ) )
          .topRadius( 50 )
          .bottomRadius( 50 )
          .relativeHoleRadius( 0.2 )
          .teeth( 6 )
          .details( 0.5 )
          .build();
        draw();
    }

    // tube
    {
        a = builder.tube()
          .startPoint( Vec3( 0, 0, 0 ) )
          .endPoint( Vec3( 30, 50, 70 ) )
          .topRadius( 30 )
          .bottomRadius( 40 )
          .relativeHoleRadius( 0.8 )
          .topScale( 2.0 )
          .bottomScale( 1.0 )
          .details( 0.1 )
          .build();
        b = builder.tube()
          .startPoint( Vec3( 10, 20, 30 ) )
          .endPoint( Vec3( 20, 40, 60 ) )
          .topRadius( 20 )
          .bottomRadius( 20 )
          .relativeHoleRadius( 0.2 )
          .topScale( 1.5 )
          .bottomScale( 3.0 )
          .details( 0.5 )
          .build();
        draw();
    }

    // sphere
    {
        a = builder.sphere()
          .radius( 70 )
          .details( 0.1 )
          .build();
        b = builder.sphere()
          .radius( 40 )
          .position( Vec3( 30, 40, 50 ) )
          .details( 0.5 )
          .build();
        draw();
    }
}




void draw() {

    floor = Vec3( 0 );
    // add
    mesh = a | b;
    mesh.tools().transform().position( tower + floor ).run();
    room += mesh;

    floor += FLOOR_SHIFT;
    // subtract
    mesh = a - b;
    mesh.tools().transform().position( tower + floor ).run();
    room += mesh;

    floor += FLOOR_SHIFT;
    // intersect
    mesh = a &amp;amp; b;
    mesh.tools().transform().position( tower + floor ).run();
    room += mesh;

    tower += TOWER_SHIFT;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
When 3D-Coat is launched, you get the following:&lt;br /&gt;
&lt;iframe width=&quot;619&quot; height=&quot;367&quot; src=&quot;https://sketchfab.com/models/0c63da07c04b443c8635d2e6041d7eec/embed&quot; frameborder=&quot;0&quot; allowfullscreen mozallowfullscreen=&quot;true&quot; webkitallowfullscreen=&quot;true&quot; onmousewheel=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;br /&gt;
&lt;br /&gt;Pay attention to the wireframe density: it is different for each mesh and is maintained after boolean operations.&lt;br /&gt;
&lt;br /&gt;
The code can be reduced, knowing that `&lt;code&gt;MeshX::build()&lt;/code&gt;` и `&lt;code&gt;ToolsX::run()&lt;/code&gt;` can be &lt;a href=&quot;https://en.wikipedia.org/wiki/Function_object&quot;&gt;functors&lt;/a&gt;. That means we can write:&lt;br /&gt;
&lt;pre&gt;&lt;code class=&quot;c++&quot;&gt;        ...
        a = builder.sphere()
          .radius( 70 )
          .details( 0.1 )
          ();
        ...&lt;/code&gt;&lt;/pre&gt;

and

&lt;pre&gt;&lt;code class=&quot;c++&quot;&gt;        ...
        mesh.tools().transform().position( tower + floor )();
        ...&lt;/code&gt;&lt;/pre&gt;

with the same result.
</content><link rel='replies' type='application/atom+xml' href='http://signmotion.blogspot.com/feeds/7947087577685095133/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2909062909816541374/7947087577685095133?isPopup=true' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2909062909816541374/posts/default/7947087577685095133'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2909062909816541374/posts/default/7947087577685095133'/><link rel='alternate' type='text/html' href='http://signmotion.blogspot.com/2015/12/primitives-scripting-3dcoat-en.html' title='Primitives and Scripting: what you can do already'/><author><name>Andrii</name><uri>http://www.blogger.com/profile/02715216472597824596</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjcrHHkyfsW8m8HmZZeyd2fhzwEl-shXbCxnYVY_mVq7uJpe5QET9SerP_bCPeO4YEBlXJT44IRPOcL7VtgFJsDqXwfppdES-fdokbXX0-11jdBQAyipvURKBH3N-Wh2VCye2U-W4nsp6zPgNSyi7g6gFgmmo34dH_oL_FTXf31U65BXQ/s220/Andrey-400x.png'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhyWcFFwKnt_iCmp0WuMLlpTTw7t3f0Ue2zUpoFF6cS85zJNCDS9shg2jN0WObPHkjeuzePuJ9T5RTpM-dVhMIHNCNTYYzcd6xgZNvgcFGScD4xkyEPpORnI8hLHjq4SY1eG8FwuiunXnlH/s72-c/primitives-boolean-scripting-3d-coat.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2909062909816541374.post-4417369071460416741</id><published>2015-12-14T11:25:00.000+02:00</published><updated>2016-03-22T14:50:26.134+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="3D-Coat"/><category scheme="http://www.blogger.com/atom/ns#" term="AngelScript"/><category scheme="http://www.blogger.com/atom/ns#" term="Russian"/><title type='text'>Примитивы и скриптинг: что уже можно</title><content type='html'>&lt;div class=&quot;img-desc&quot;&gt;&lt;img alt=&quot;Primitives, boolean operations, 3D-Coat, AngelScript&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhyWcFFwKnt_iCmp0WuMLlpTTw7t3f0Ue2zUpoFF6cS85zJNCDS9shg2jN0WObPHkjeuzePuJ9T5RTpM-dVhMIHNCNTYYzcd6xgZNvgcFGScD4xkyEPpORnI8hLHjq4SY1eG8FwuiunXnlH/s1600/primitives-boolean-scripting-3d-coat.png&quot; /&gt;&lt;/div&gt;
&lt;div class=&quot;read-in&quot;&gt;&lt;a href=&quot;/2015/12/primitives-scripting-3dcoat-en.html&quot; title=&quot;Primitives and Scripting: what you can do already&quot;&gt;&amp;sect; Read in English &amp;rarr;&lt;/a&gt;&lt;/div&gt;
Добавил &lt;b&gt;базовый набор&lt;/b&gt; примитивов: теперь в &lt;a href=&quot;http://3d-coat.com&quot;&gt;3D-Coat&lt;/a&gt; их можно создавать в скриптах. Плюс, с ними уже можно кое-что делать: менять позицию на экране, масштабировать. Это немного, но заложена основа, а новый подход к скриптингу легко масштабируется и, надеюсь, проще для освоения (старые возможности - &lt;a href=&quot;http://j.mp/3dc-angelscript&quot;&gt;остались&lt;/a&gt;: написанные ранее скрипты будут работать). В версии &lt;a href=&quot;http://3d-coat.com/forum/index.php?showtopic=17076&quot;&gt;4.5.26&lt;/a&gt; и выше это новое уже будет.
&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;Код:
&lt;br /&gt;
&lt;pre&gt;&lt;code class=&quot;c++&quot;&gt;// глобальные переменные позволяют нам не заморачиваться
// с передачей параметров в методы, сделав т.о. код короче
const Vec3  TOWER_SHIFT( 0, 0, 200 );
const Vec3  FLOOR_SHIFT( 0, 200, 0 );
Vec3  tower = TOWER_SHIFT * (-4.5);
Vec3  floor( 0 );
Mesh  a, b, mesh;
// с помощью `builder` создаём разные меши
Builder  builder;
// используем `room` для формирования сцены
SculptRoom  room;


void main() {

    // подготавливаем сцену
    room.clear().toSurface();

    // капсула
    {
        // первый меш
        a = builder.capsule()
          // подготавливаем к строительству
          .startPosition( Vec3( 0 ) )
          .endPosition( Vec3( 40, 50, 60 ) )
          .startRadius( 30 )
          .endRadius( 50 )
          // плотность сетки
          .details( 0.1 )
          // строим
          .build();
        // второй меш
        b = builder.capsule()
          .startPosition( Vec3( 0 ) )
          .endPosition( Vec3( 20, 30, 40 ) )
          .startRadius( 20 )
          .endRadius( 30 )
          .position( Vec3( 20, 30, 40 ) )
          .details( 0.5 )
          .build();
        // рисуем меши `a` и `b`
        // см. реализацию draw() в конце листинга
        draw();
    }

    // конус
    {
        a = builder.cone()
          .radius( 50 )
          .height( 120 )
          .details( 0.1 )
          .build();
        b = builder.cone()
          .radius( 40 )
          .height( 80 )
          .position( Vec3( 10, 20, 30 ) )
          .details( 0.5 )
          .build();
        draw();
    }

    // кубоид
    {
        a = builder.cuboid()
          .side( Vec3( 100, 80, 60 ) )
          .details( 0.1 )
          .build();
        b = builder.cuboid()
          .side( Vec3( 30, 50, 70 ) )
          .position( Vec3( 20, 30, 40 ) )
          .details( 0.5 )
          .build();
        draw();
    }

    // цилиндр
    {
        a = builder.cylinder()
          .positionTop( Vec3( 80, 0, 0 ) )
          .positionBottom( Vec3( 0, 0, 0 ) )
          .radiusTop( 40 )
          .radiusBottom( 50 )
          .details( 0.1 )
          .build();
        b = builder.cylinder()
          .positionTop( Vec3( 70, 0, 10 ) )
          .positionBottom( Vec3( 0, 0, 0 ) )
          .radiusTop( 20 )
          .radiusBottom( 30 )
          .position( Vec3( 20, 30, 40 ) )
          .details( 0.5 )
          .build();
        draw();
    }

    // эллипсоид
    {
        a = builder.ellipsoid()
          .radius( Vec3( 80, 60, 40 ) )
          .details( 0.1 )
          .build();
        b = builder.ellipsoid()
          .radius( Vec3( 20, 40, 60 ) )
          .position( Vec3( 20, 30, 40 ) )
          .details( 0.5 )
          .build();
        draw();
    }

    // шестерёнка
    {
        a = builder.gear()
          .startPoint( Vec3( 0, 0, 0 ) )
          .endPoint( Vec3( 90, 90, 90 ) )
          .topRadius( 30 )
          .bottomRadius( 50 )
          .relativeHoleRadius( 0.3 )
          .depth( 0.5 )
          .sharpness( 0.2 )
          .teeth( 3 )
          .details( 0.1 )
          .build();
        b = builder.gear()
          .startPoint( Vec3( 20, 20, 20 ) )
          .endPoint( Vec3( 50, 50, 50 ) )
          .topRadius( 50 )
          .bottomRadius( 50 )
          .relativeHoleRadius( 0.3 )
          .depth( 0.2 )
          .sharpness( 1.0 )
          .teeth( 6 )
          .details( 0.5 )
          .build();
        draw();
    }

    // энгон
    {
        a = builder.ngon()
          .startPoint( Vec3( 0, 0, 0 ) )
          .endPoint( Vec3( 90, 90, 90 ) )
          .topRadius( 30 )
          .bottomRadius( 40 )
          .relativeHoleRadius( 0.3 )
          .teeth( 3 )
          .details( 0.1 )
          .build();
        b = builder.ngon()
          .startPoint( Vec3( 20, 20, 20 ) )
          .endPoint( Vec3( 50, 50, 50 ) )
          .topRadius( 50 )
          .bottomRadius( 50 )
          .relativeHoleRadius( 0.2 )
          .teeth( 6 )
          .details( 0.5 )
          .build();
        draw();
    }

    // труба
    {
        a = builder.tube()
          .startPoint( Vec3( 0, 0, 0 ) )
          .endPoint( Vec3( 30, 50, 70 ) )
          .topRadius( 30 )
          .bottomRadius( 40 )
          .relativeHoleRadius( 0.8 )
          .topScale( 2.0 )
          .bottomScale( 1.0 )
          .details( 0.1 )
          .build();
        b = builder.tube()
          .startPoint( Vec3( 10, 20, 30 ) )
          .endPoint( Vec3( 20, 40, 60 ) )
          .topRadius( 20 )
          .bottomRadius( 20 )
          .relativeHoleRadius( 0.2 )
          .topScale( 1.5 )
          .bottomScale( 3.0 )
          .details( 0.5 )
          .build();
        draw();
    }

    // сфера
    {
        a = builder.sphere()
          .radius( 70 )
          .details( 0.1 )
          .build();
        b = builder.sphere()
          .radius( 40 )
          .position( Vec3( 30, 40, 50 ) )
          .details( 0.5 )
          .build();
        draw();
    }
}




// выполняет булевы операции над мешами `a` и `b`
// и добавляет результат на сцену
void draw() {

    floor = Vec3( 0 );
    // объединение (add)
    mesh = a | b;
    mesh.tools().transform().position( tower + floor ).run();
    room += mesh;

    floor += FLOOR_SHIFT;
    // вычитание (subtract)
    mesh = a - b;
    mesh.tools().transform().position( tower + floor ).run();
    room += mesh;

    floor += FLOOR_SHIFT;
    // пересечение (intersect)
    mesh = a &amp;amp; b;
    mesh.tools().transform().position( tower + floor ).run();
    room += mesh;

    tower += TOWER_SHIFT;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
Запустив скрипт в 3D-Coat, получаем такую картинку:&lt;br /&gt;
&lt;iframe width=&quot;619&quot; height=&quot;367&quot; src=&quot;https://sketchfab.com/models/0c63da07c04b443c8635d2e6041d7eec/embed&quot; frameborder=&quot;0&quot; allowfullscreen mozallowfullscreen=&quot;true&quot; webkitallowfullscreen=&quot;true&quot; onmousewheel=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;br /&gt;
&lt;br /&gt;Обратите внимание на плотность сетки: она у фигур разная и сохраняется после булевых операций.&lt;br /&gt;
&lt;br /&gt;
Код можно сократить, зная, что методы `&lt;code&gt;MeshX::build()&lt;/code&gt;` и `&lt;code&gt;ToolsX::run()&lt;/code&gt;` могут выступать &lt;a href=&quot;https://ru.wikipedia.org/wiki/%D0%A4%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%BE%D0%BD%D0%B0%D0%BB%D1%8C%D0%BD%D1%8B%D0%B9_%D0%BE%D0%B1%D1%8A%D0%B5%D0%BA%D1%82&quot;&gt;функторами&lt;/a&gt;. Т.е. можем писать:&lt;br /&gt;
&lt;pre&gt;&lt;code class=&quot;c++&quot;&gt;        ...
        a = builder.sphere()
          .radius( 70 )
          .details( 0.1 )
          ();
        ...&lt;/code&gt;&lt;/pre&gt;

и

&lt;pre&gt;&lt;code class=&quot;c++&quot;&gt;        ...
        mesh.tools().transform().position( tower + floor )();
        ...&lt;/code&gt;&lt;/pre&gt;

с тем же результатом.
</content><link rel='replies' type='application/atom+xml' href='http://signmotion.blogspot.com/feeds/4417369071460416741/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2909062909816541374/4417369071460416741?isPopup=true' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2909062909816541374/posts/default/4417369071460416741'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2909062909816541374/posts/default/4417369071460416741'/><link rel='alternate' type='text/html' href='http://signmotion.blogspot.com/2015/12/primitives-scripting-3dcoat.html' title='Примитивы и скриптинг: что уже можно'/><author><name>Andrii</name><uri>http://www.blogger.com/profile/02715216472597824596</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjcrHHkyfsW8m8HmZZeyd2fhzwEl-shXbCxnYVY_mVq7uJpe5QET9SerP_bCPeO4YEBlXJT44IRPOcL7VtgFJsDqXwfppdES-fdokbXX0-11jdBQAyipvURKBH3N-Wh2VCye2U-W4nsp6zPgNSyi7g6gFgmmo34dH_oL_FTXf31U65BXQ/s220/Andrey-400x.png'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhyWcFFwKnt_iCmp0WuMLlpTTw7t3f0Ue2zUpoFF6cS85zJNCDS9shg2jN0WObPHkjeuzePuJ9T5RTpM-dVhMIHNCNTYYzcd6xgZNvgcFGScD4xkyEPpORnI8hLHjq4SY1eG8FwuiunXnlH/s72-c/primitives-boolean-scripting-3d-coat.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2909062909816541374.post-7453178485056613413</id><published>2015-11-23T21:00:00.000+02:00</published><updated>2016-02-24T10:07:12.469+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="3D-Coat"/><category scheme="http://www.blogger.com/atom/ns#" term="AngelScript"/><category scheme="http://www.blogger.com/atom/ns#" term="English"/><title type='text'>New scripting in 3D-Coat</title><content type='html'>&lt;div class=&quot;img-desc&quot;&gt;&lt;img alt=&quot;3D-Coat AngelScript&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiOTKobDe1fz7qauIuTKceIIwOwYKwt0ch-R3uD3zcU-MadEAB2wgT6XXD-wR0MPLERS4ElqUBpKZPbhFNlQ2nX27cVlE9IPeLtSXuizPVW0T6Hc3ZWSDkg8GCqL2umHtX9X3aMJqr6QSLT/s1600/spheres-scripting-3d-coat.png&quot; /&gt;&lt;/div&gt;
&lt;div class=&quot;read-in&quot;&gt;&lt;a href=&quot;/2015/11/new-scripting-3d-coat.html&quot; title=&quot;Новый скриптинг 3D-Coat&quot;&gt;&amp;sect; Читать по-русски &amp;rarr;&lt;/a&gt;&lt;/div&gt;
The most difficult thing in programming is to understand an application&#39;s architecture.  At least it should be such that &lt;strong&gt;the program would be handy to use correctly, and unhandy to use incorrectly&lt;/strong&gt;. While working with scripting for &lt;a href=&quot;http://3dcoat.com/&quot; title=&quot;3D good modelling&quot;&gt;3D-Coat&lt;/a&gt; I try to follow that rule. (&lt;i&gt;Reasonable&lt;/i&gt; following &lt;a href=&quot;https://en.wikipedia.org/wiki/SOLID_%28object-oriented_design%29&quot; title=&quot;SOLID&quot;&gt;OOP principles&lt;/a&gt; – even without discussions). So here&#39;s what we get...&lt;br /&gt;&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;pre&gt;&lt;code class=&quot;c++&quot;&gt;void main() {

    // preparing a scene
    SculptRoom  sculpt;
    sculpt.clear().toSurface();

    Mesh  a, b;
    const Vec3  dir = Vec3( 0, 1, 0 );

    // I) add
    float  delta = 0;
    Vec3  shift = dir * delta;
    {
        build( a, b, shift );
        const Mesh  ab = a | b;
        sculpt += ab;
    }

    // II) subtruct
    delta += 200;
    shift = dir * delta;
    {
        build( a, b, shift );
        const Mesh  ab = a - b;
        sculpt += ab;
    }

    // III) intersect
    delta += 200;
    shift = dir * delta;
    {
        build( a, b, shift );
        const Mesh  ab = a &amp;amp; b;
        sculpt += ab;
    }
}


void build( Mesh &amp;amp;out a, Mesh &amp;amp;out b, const Vec3 &amp;amp;in shift ) {

    Builder  builder;

    const Vec3  pa( 0 );
    a = builder.sphere()
      .radius( 90 )
      .position( pa + shift )
      .details( 0.1 )
      .build();

    const Vec3  pb( 30, 40, 50 );
    b = builder.sphere()
      .radius( 50 )
      .position( pb + shift )
      .details( 0.5 )
      .build();
}&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
Launching this script in &lt;a href=&quot;http://3dcoat.com/&quot; title=&quot;3D model fast creator&quot;&gt;3D-Coat&lt;/a&gt;, we will see:&lt;br /&gt;
&lt;br /&gt;
&lt;iframe allowfullscreen=&quot;&quot; frameborder=&quot;0&quot; height=&quot;367&quot; mozallowfullscreen=&quot;true&quot; onmousewheel=&quot;&quot; src=&quot;https://sketchfab.com/models/46b30e46a95a4c2ba508efa08c0cadfe/embed&quot; webkitallowfullscreen=&quot;true&quot; width=&quot;619&quot;&gt;&lt;/iframe&gt;
&lt;br /&gt;
Why is such a picture understandable after reading a string of code, with its comments. Notice: the sphere&#39;s detail state remains the same after adding, subtraction and intersection.
&lt;br /&gt;Script can be written more compact when excluding command `&lt;code&gt;Mesh ab&lt;/code&gt;`:&lt;br /&gt;
&lt;pre&gt;&lt;code class=&quot;c++&quot;&gt;{
    build( a, b, shift );
    sculpt += a | b;
}&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
This is my first post with new scripting architecture. Syntax is a red thread, which I would maintain. Also there is a &lt;a href=&quot;https://docs.google.com/presentation/d/1EdRWnW-tECzB1bwKUDO8zfJkrQscxHluHams4ssQRcQ/edit?usp=sharing&quot; title=&quot;3D-Coat Scripting tech presentation&quot;&gt;short presentation&lt;/a&gt; which demonstrates how I plan to expand &lt;a href=&quot;http://3d-coat.com/&quot; title=&quot;3D effective drawing&quot;&gt;3D-Coat&#39;s&lt;/a&gt; possibilities. &lt;b&gt;Please let me  know if there is something that you need &lt;i&gt;first&lt;/i&gt;&lt;/b&gt;. Old code works too, but when a proper substitute appears old code is marked as &lt;i&gt;DEPRECATED&lt;/i&gt;.&lt;br /&gt;
&lt;br /&gt;
In the near term I will add new primitives and will expand this review.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Updated 14/12/2015&lt;/b&gt;&lt;br /&gt;
See &quot;&lt;a href=&quot;http://signmotion.blogspot.com/2015/12/primitives-scripting-3dcoat-en.html&quot;&gt;Primitives and Scripting: what you can do already&lt;/a&gt;&quot;.
&lt;br /&gt;
</content><link rel='replies' type='application/atom+xml' href='http://signmotion.blogspot.com/feeds/7453178485056613413/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2909062909816541374/7453178485056613413?isPopup=true' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2909062909816541374/posts/default/7453178485056613413'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2909062909816541374/posts/default/7453178485056613413'/><link rel='alternate' type='text/html' href='http://signmotion.blogspot.com/2015/11/new-scripting-3d-coat-eng.html' title='New scripting in 3D-Coat'/><author><name>Andrii</name><uri>http://www.blogger.com/profile/02715216472597824596</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjcrHHkyfsW8m8HmZZeyd2fhzwEl-shXbCxnYVY_mVq7uJpe5QET9SerP_bCPeO4YEBlXJT44IRPOcL7VtgFJsDqXwfppdES-fdokbXX0-11jdBQAyipvURKBH3N-Wh2VCye2U-W4nsp6zPgNSyi7g6gFgmmo34dH_oL_FTXf31U65BXQ/s220/Andrey-400x.png'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiOTKobDe1fz7qauIuTKceIIwOwYKwt0ch-R3uD3zcU-MadEAB2wgT6XXD-wR0MPLERS4ElqUBpKZPbhFNlQ2nX27cVlE9IPeLtSXuizPVW0T6Hc3ZWSDkg8GCqL2umHtX9X3aMJqr6QSLT/s72-c/spheres-scripting-3d-coat.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2909062909816541374.post-7776384771462357921</id><published>2015-11-23T20:28:00.002+02:00</published><updated>2016-02-24T10:08:05.104+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="3D-Coat"/><category scheme="http://www.blogger.com/atom/ns#" term="AngelScript"/><category scheme="http://www.blogger.com/atom/ns#" term="Russian"/><title type='text'>Новый скриптинг 3D-Coat</title><content type='html'>&lt;div class=&quot;img-desc&quot;&gt;&lt;img alt=&quot;3D-Coat AngelScript&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiOTKobDe1fz7qauIuTKceIIwOwYKwt0ch-R3uD3zcU-MadEAB2wgT6XXD-wR0MPLERS4ElqUBpKZPbhFNlQ2nX27cVlE9IPeLtSXuizPVW0T6Hc3ZWSDkg8GCqL2umHtX9X3aMJqr6QSLT/s1600/spheres-scripting-3d-coat.png&quot; /&gt;&lt;/div&gt;
&lt;div class=&quot;read-in&quot;&gt;&lt;a href=&quot;/2015/11/new-scripting-3d-coat-eng.html&quot; title=&quot;New scripting in 3D-Coat&quot;&gt;&amp;sect; Read in English &amp;rarr;&lt;/a&gt;&lt;/div&gt;
В программировании важно продумать архитектуру приложения. Как минимум, она должна быть такой, чтобы библиотеку было &lt;strong&gt;удобно использовать правильно и неудобно неправильно&lt;/strong&gt;. Работая со скриптингом для &lt;a href=&quot;http://3dcoat.com/&quot; title=&quot;Удобный 3D-редактор&quot;&gt;Коута&lt;/a&gt;, я стараюсь следовать &lt;strike&gt;этой заповеди&lt;/strike&gt; этому принципу. (&lt;i&gt;Разумное&lt;/i&gt; следование &lt;a href=&quot;https://ru.wikipedia.org/wiki/SOLID_%28%D0%BE%D0%B1%D1%8A%D0%B5%D0%BA%D1%82%D0%BD%D0%BE-%D0%BE%D1%80%D0%B8%D0%B5%D0%BD%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5%29&quot; title=&quot;OOP SOLID&quot;&gt;принципам ООП&lt;/a&gt; - это даже не обсуждается). И вот что получается...&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;pre&gt;&lt;code class=&quot;c++&quot;&gt;// Создаём две сферы и объединяем их тремя способами.
void main() {

    // подготавливаем сцену
    SculptRoom  sculpt;
    sculpt.clear().toSurface();

    Mesh  a, b;
    const Vec3  dir = Vec3( 0, 1, 0 );

    // I) add
    float  delta = 0;
    Vec3  shift = dir * delta;
    {
        build( a, b, shift );
        const Mesh  ab = a | b;
        sculpt += ab;
    }

    // II) subtruct
    delta += 200;
    shift = dir * delta;
    {
        build( a, b, shift );
        const Mesh  ab = a - b;
        sculpt += ab;
    }

    // III) intersect
    delta += 200;
    shift = dir * delta;
    {
        build( a, b, shift );
        const Mesh  ab = a &amp;amp; b;
        sculpt += ab;
    }
}


void build( Mesh &amp;amp;out a, Mesh &amp;amp;out b, const Vec3 &amp;amp;in shift ) {

    Builder  builder;

    const Vec3  pa( 0 );
    a = builder.sphere()
      .radius( 90 )
      .position( pa + shift )
      .details( 0.1 )
      .build();

    const Vec3  pb( 30, 40, 50 );
    b = builder.sphere()
      .radius( 50 )
      .position( pb + shift )
      .details( 0.5 )
      .build();
}&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
Запускаем скрипт в &lt;a href=&quot;http://3dcoat.com/&quot; title=&quot;Быстрое 3D-моделирование&quot;&gt;Коте&lt;/a&gt; (&lt;i&gt;кстати, во Вт, 24/11/15 сделаю, чтобы скрипт можно было пускать при старте 3D-Coat&#39;а&lt;/i&gt;) и видим:&lt;br /&gt;
&lt;br /&gt;
&lt;iframe allowfullscreen=&quot;&quot; frameborder=&quot;0&quot; height=&quot;367&quot; mozallowfullscreen=&quot;true&quot; onmousewheel=&quot;&quot; src=&quot;https://sketchfab.com/models/46b30e46a95a4c2ba508efa08c0cadfe/embed&quot; webkitallowfullscreen=&quot;true&quot; width=&quot;619&quot;&gt;&lt;/iframe&gt;
&lt;br /&gt;
Почему такая картинка - понятно, если прочесть код и, может быть, комментарии к нему. Обратите внимание: детализация сфер при добавлении, вычитании и пересечении сохраняется.
&lt;br /&gt;Скрипт можно записать более компактно, исключив декларацию `&lt;code&gt;Mesh ab&lt;/code&gt;`:&lt;br /&gt;
&lt;pre&gt;&lt;code class=&quot;c++&quot;&gt;{
    build( a, b, shift );
    sculpt += a | b;
}&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
Это первая заметка с новой архитектурой скриптинга. Синтаксис - красная нить, которой буду придерживаться. Также есть небольшая &lt;a href=&quot;https://docs.google.com/presentation/d/1EdRWnW-tECzB1bwKUDO8zfJkrQscxHluHams4ssQRcQ/edit?usp=sharing&quot; target=&quot;_blank&quot;&gt;презентация&lt;/a&gt;, в которой видно, каким образом планирую расширять возможности &lt;a href=&quot;http://3dcoat.com/&quot; title=&quot;Скриптование: 3D-Coat и AngelScript&quot;&gt;Coat&#39;а&lt;/a&gt;. &lt;b&gt;Говорите, если что-то понадобится Вам &lt;i&gt;быстрее&lt;/i&gt;&lt;/b&gt;. Старый код - тоже работает, но, при появлении подходящей замены, помечается как &lt;i&gt;DEPRECATED&lt;/i&gt;.&lt;br /&gt;
&lt;br /&gt;
В ближайшее время добавлю новые примитивы и дополню этот обзор.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Updated 14/12/2015&lt;/b&gt;&lt;br /&gt;
См. &quot;&lt;a href=&quot;http://signmotion.blogspot.com/2015/12/primitives-scripting-3dcoat.html&quot;&gt;Примитивы в 3D-Coat: что уже можно&lt;/a&gt;&quot;.
&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://signmotion.blogspot.com/feeds/7776384771462357921/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2909062909816541374/7776384771462357921?isPopup=true' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2909062909816541374/posts/default/7776384771462357921'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2909062909816541374/posts/default/7776384771462357921'/><link rel='alternate' type='text/html' href='http://signmotion.blogspot.com/2015/11/new-scripting-3d-coat.html' title='Новый скриптинг 3D-Coat'/><author><name>Andrii</name><uri>http://www.blogger.com/profile/02715216472597824596</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjcrHHkyfsW8m8HmZZeyd2fhzwEl-shXbCxnYVY_mVq7uJpe5QET9SerP_bCPeO4YEBlXJT44IRPOcL7VtgFJsDqXwfppdES-fdokbXX0-11jdBQAyipvURKBH3N-Wh2VCye2U-W4nsp6zPgNSyi7g6gFgmmo34dH_oL_FTXf31U65BXQ/s220/Andrey-400x.png'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiOTKobDe1fz7qauIuTKceIIwOwYKwt0ch-R3uD3zcU-MadEAB2wgT6XXD-wR0MPLERS4ElqUBpKZPbhFNlQ2nX27cVlE9IPeLtSXuizPVW0T6Hc3ZWSDkg8GCqL2umHtX9X3aMJqr6QSLT/s72-c/spheres-scripting-3d-coat.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2909062909816541374.post-9028405737312365879</id><published>2015-11-10T21:00:00.000+02:00</published><updated>2016-02-24T10:09:01.017+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="3D-Coat"/><category scheme="http://www.blogger.com/atom/ns#" term="AngelScript"/><category scheme="http://www.blogger.com/atom/ns#" term="English"/><title type='text'>Layers in Sculpt Room via Scripts</title><content type='html'>&lt;div class=&quot;img-desc&quot;&gt;&lt;img alt=&quot;knight 3D-Coat voxel&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEijurpWUh5pGoSh9pMUSH8SDuOiNDBqcTQHPmLo1jJbtnYN1V8Hw2Zdxd0Fyllud8mXXQGy_fG1I15yZMNdM6jwfsFJGwp2nmpiL4BJy92ddVdqyz5Ta-x8fZ7r2YIVSpgMOldscy-SS3Kw/s1600/voxel-knight-3d-coat.jpg&quot; /&gt;&lt;cite&gt;@&lt;a href=&quot;https://plus.google.com/+ChristophWerner/posts&quot;&gt;Christoph Werner&lt;/a&gt;&lt;/cite&gt;&lt;/div&gt;
&lt;div class=&quot;read-in&quot;&gt;&lt;a href=&quot;/2015/11/volume-layers-script.html&quot; title=&quot;Слои скриптами в SculptRoom&quot;&gt;&amp;sect; Читать по-русски &amp;rarr;&lt;/a&gt;&lt;/div&gt;
Yes, you can operate with layers via scripts in 3D-Coat! Right now, I will show and explain everything...&lt;br /&gt;
&lt;br /&gt;
In order to memorize methods faster (we want to focus on the result and not get into the habit of constantly referring to &lt;a href=&quot;http://j.mp/3dc-angelscript&quot;&gt;manual&lt;/a&gt;, right?), I will explain what I was thinking while making them. But first take a look at this tree:&lt;br /&gt;
&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;img alt=&quot;menu voxels&quot; border=&quot;0&quot; height=&quot;288&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi_I55ADDiexm9kEO3zzuQJvrK_8rmbEuRp_LPU2FMAvRaNGW57rURT9B8Sn_1iptf2SXIKHkfAAyl-Ko8ks0-Ww4NcwRfrLoyZ2aATeQ8tOANmy6dBjlvXQHWlYPzJ-Rbpju9zyBRPvH46/s320/voxtree.png&quot; width=&quot;320&quot; /&gt;
&lt;/div&gt;
Head, Body, Arms, Legs – almost a human. 3D-Coat &lt;a href=&quot;https://youtu.be/PicXftYaqEw&quot;&gt;lets you create&lt;/a&gt; as many layers as you like. And each of them is able to contain a complex layers tree.&lt;br /&gt;
&lt;br /&gt;
In the &lt;a href=&quot;http://signmotion.blogspot.com/2015/11/3d-coat.html&quot;&gt;first post&lt;/a&gt; I promised to be concise. So, the code itself:&lt;br /&gt;
&lt;pre&gt;&lt;code class=&quot;c++&quot;&gt;void main() {

    // preparing a scene
    Vox  v;
    v.clearScene();

    // building a tree with v-layers
    v
      .appendToParent( &quot;Head&quot; )
      .appendToParent( &quot;Body&quot; )
        .append(         &quot;Neck&quot; )
        .appendToParent( &quot;Left arm&quot; )
        .appendToParent( &quot;Right arm&quot; )
        .appendToParent( &quot;Heart&quot; )
        .appendToParent( &quot;Left leg&quot; )
        .appendToParent( &quot;Right leg&quot; )

      // return to the layer &quot;Head&quot;, switch it
      // to &quot;Surface mode&quot; and attach
      .to( &quot;Head&quot; ).toSurface()
        .append( &quot;Eye&quot; )
        .appendToParent( &quot;Lamps&quot; )
    ;

    // removing a first layer from a scene
    v.firstForRoot().remove();
}&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
Do you see patterns of methods? `append()`, `appendToParent()`, `appendToRoot()`, `forEach()`, `forRootEach()`, ... - as you might have noticed, the names themselves are pretty self-explanatory. Compare the code with the resulting picture. It should be easy to figure out without the need to frequently refer to documentation, which command does what.&lt;br /&gt;
&lt;br /&gt;
After looking through the libraries for working with &#39;trees&#39; I found that it is
most intuitively done in &lt;a href=&quot;https://jquery.com/&quot;&gt;JQuery&lt;/a&gt;. Are you familiar with it? Then I won&#39;t explain anything!) The only thing that should be taken into account during  developing: class `Vox` works with &lt;a title=&quot;Download 3DCoat&quot; href=&quot;http://3dcoat.com/download/stable-release/&quot;&gt;3D-Coat&#39;s&lt;/a&gt; UI, so introduced in code Vox-methods select layers before any kind of operation.&lt;br /&gt;
&lt;br /&gt;
So, working on layers:&lt;br /&gt;
&lt;pre&gt;&lt;code class=&quot;c++&quot;&gt;void main() {

    // creating a tree - see above
    // ...

    // #1
    // calling invert() for all v-layer
    // see below
    v.forRootEach( &quot;invert&quot; );

    // #2
    // moving to the &quot;Body&quot; and invert() for it and childs
    v.to( &quot;Body&quot; ).call( &quot;invert&quot; ).forEach( &quot;invert&quot; );
}


void invert() {
    Vox  v;
    v.isSurface() ? v.toVoxel() : v.toSurface();
    Wait( 50 );
}&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
I think that previously described methods are enough for processing any tree. But &lt;a title=&quot;Chief&quot; href=&quot;https://facebook.com/andrew.shpagin&quot;&gt;Andrew&amp;nbsp;Shpagin&lt;/a&gt; says it is not. Here you have another variant:&lt;br /&gt;
&lt;pre&gt;&lt;code class=&quot;c++&quot;&gt;    // access by index on all childs of &quot;Head&quot;
    v.to( &quot;Head&quot; ).call( &quot;invert&quot; );
    for ( int i = 0; i &amp;lt; v.count(); ++i ) {
        v.at( i ).call( &quot;invert&quot; ).parent();
        Wait( 100 );
    }&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
Also, &lt;b&gt;all&lt;/b&gt; VoxTree options are available for &#39;Vox&#39; class via scripts:&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjXbjvatdESL1w3iKS-Ncht6zUwNcPKigiC4aXSsU8LWkK_8bVNCbb1by77TsgucWZKGM9BEzR8GTGLtIue17ezFb2izU4btR4j_nKphlEOycIzozer4q40cZ5neIoXQ52jzP7aYaan95Oj/s1600/surface.png&quot; /&gt;&lt;/div&gt;
&lt;br /&gt;
What I also would like to add is a more concise constructor. Later. I need to improve operations with primitives, and there are a lot of them...&lt;br /&gt;
&lt;br /&gt;
P.S. Btw, the example tree has a &quot;real prototype&quot;:&lt;br /&gt;
&lt;br /&gt;
&lt;iframe allowfullscreen=&quot;&quot; frameborder=&quot;0&quot; height=&quot;367&quot; mozallowfullscreen=&quot;true&quot; onmousewheel=&quot;&quot; src=&quot;https://sketchfab.com/models/91eb0eb061024bf1bc5e3eb5ffe385d8/embed&quot; webkitallowfullscreen=&quot;true&quot; width=&quot;619&quot;&gt;&lt;/iframe&gt;
</content><link rel='replies' type='application/atom+xml' href='http://signmotion.blogspot.com/feeds/9028405737312365879/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2909062909816541374/9028405737312365879?isPopup=true' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2909062909816541374/posts/default/9028405737312365879'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2909062909816541374/posts/default/9028405737312365879'/><link rel='alternate' type='text/html' href='http://signmotion.blogspot.com/2015/11/layers-via-scripts-3dcoat.html' title='Layers in Sculpt Room via Scripts'/><author><name>Andrii</name><uri>http://www.blogger.com/profile/02715216472597824596</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjcrHHkyfsW8m8HmZZeyd2fhzwEl-shXbCxnYVY_mVq7uJpe5QET9SerP_bCPeO4YEBlXJT44IRPOcL7VtgFJsDqXwfppdES-fdokbXX0-11jdBQAyipvURKBH3N-Wh2VCye2U-W4nsp6zPgNSyi7g6gFgmmo34dH_oL_FTXf31U65BXQ/s220/Andrey-400x.png'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEijurpWUh5pGoSh9pMUSH8SDuOiNDBqcTQHPmLo1jJbtnYN1V8Hw2Zdxd0Fyllud8mXXQGy_fG1I15yZMNdM6jwfsFJGwp2nmpiL4BJy92ddVdqyz5Ta-x8fZ7r2YIVSpgMOldscy-SS3Kw/s72-c/voxel-knight-3d-coat.jpg" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2909062909816541374.post-1169041022948452064</id><published>2015-11-10T20:11:00.001+02:00</published><updated>2016-02-24T10:10:06.452+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="3D-Coat"/><category scheme="http://www.blogger.com/atom/ns#" term="AngelScript"/><category scheme="http://www.blogger.com/atom/ns#" term="Russian"/><title type='text'>Слои скриптами в SculptRoom</title><content type='html'>&lt;div class=&quot;img-desc&quot;&gt;
&lt;img alt=&quot;knight 3D-Coat&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEijurpWUh5pGoSh9pMUSH8SDuOiNDBqcTQHPmLo1jJbtnYN1V8Hw2Zdxd0Fyllud8mXXQGy_fG1I15yZMNdM6jwfsFJGwp2nmpiL4BJy92ddVdqyz5Ta-x8fZ7r2YIVSpgMOldscy-SS3Kw/s1600/voxel-knight-3d-coat.jpg&quot; /&gt;&lt;cite&gt;@&lt;a href=&quot;https://plus.google.com/+ChristophWerner/posts&quot;&gt;Christoph Werner&lt;/a&gt;&lt;/cite&gt;&lt;/div&gt;
&lt;div class=&quot;read-in&quot;&gt;&lt;a href=&quot;/2015/11/layers-via-scripts-3dcoat.html&quot; title=&quot;Layers in Sculpt Room via Scripts&quot;&gt;&amp;sect; Read in English &amp;rarr;&lt;/a&gt;&lt;/div&gt;
Есть, есть работа с воксельными слоями в скриптах 3D-Coat!) Сейчас и расскажу, и покажу...&lt;br /&gt;
&lt;br /&gt;
Чтобы быстрее запомнить названия методов (мы ведь хотим результат, а не вечную тягу к &lt;a href=&quot;http://j.mp/3dc-angelscript&quot;&gt;документации&lt;/a&gt;), объясню чем руководствовался, создавая их. Но вначале посмотрите на это дерево:&lt;br /&gt;
&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;img border=&quot;0&quot; height=&quot;288&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi_I55ADDiexm9kEO3zzuQJvrK_8rmbEuRp_LPU2FMAvRaNGW57rURT9B8Sn_1iptf2SXIKHkfAAyl-Ko8ks0-Ww4NcwRfrLoyZ2aATeQ8tOANmy6dBjlvXQHWlYPzJ-Rbpju9zyBRPvH46/s320/voxtree.png&quot; width=&quot;320&quot; /&gt;
&lt;/div&gt;
Голова (Head), тело (Body), руки (* arm), ноги( * leg) - почти человек) 3D-Коут позволяет создавать множество слоёв. И каждый из них способен содержать... ну, Вы поняли: даже сложное дерево можно &lt;a href=&quot;https://youtu.be/PicXftYaqEw&quot; target=&quot;&quot;&gt;нарисовать в Коуте&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
В &lt;a href=&quot;http://signmotion.blogspot.com/2015/11/3d-coat.html&quot;&gt;первой заметке&lt;/a&gt; обещал быть кратким. Поэтому, сразу код:&lt;br /&gt;
&lt;pre&gt;&lt;code class=&quot;c++&quot;&gt;// Работа со &quot;слоями объёма&quot; (volume layers, сокр. v-layers)
void main() {

    // подготавливаем сцену
    Vox  v;
    v.clearScene();

    // строим дерево v-слоёв
    v
      .appendToParent( &quot;Head&quot; )
      .appendToParent( &quot;Body&quot; )
        .append(         &quot;Neck&quot; )
        .appendToParent( &quot;Left arm&quot; )
        .appendToParent( &quot;Right arm&quot; )
        .appendToParent( &quot;Heart&quot; )
        .appendToParent( &quot;Left leg&quot; )
        .appendToParent( &quot;Right leg&quot; )

      // возвращаемся к слою &quot;Head&quot;, переводим его
      // в &quot;Режим поверхности&quot; и аттачим новые
      .to( &quot;Head&quot; ).toSurface()
        .append( &quot;Eye&quot; )
        .appendToParent( &quot;Lamps&quot; )
      // Заметили как добавились последние?
      // Верно: `S`, не `V`.
    ;

    // удаляем первый (пустой) слой со сцены
    v.firstForRoot().remove();
}
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
Видите группы методов? `append()`, `appendToParent()`, `appendToRoot()`, `forEach()`, `forRootEach()`, ... - говорящие названия, если понимать, что &quot;&lt;i&gt;parent&lt;/i&gt;&quot; по англ. &quot;&lt;i&gt;родитель&lt;/i&gt;&quot;, &quot;&lt;i&gt;root&lt;/i&gt;&quot; - &quot;&lt;i&gt;корень&lt;/i&gt;&quot;, а &quot;&lt;i&gt;for each&lt;/i&gt;&quot; - &quot;&lt;i&gt;для каждого&lt;/i&gt;&quot;. Сравнивая код с результатом-картинкой, Вы &lt;strike&gt;без документации&lt;/strike&gt; без труда разберётесь кто что творит.&lt;br /&gt;
&lt;br /&gt;
Пересмотрев библиотеки для работы с деревьями, я нашёл, что наиболее естественно это дело реализовано в &lt;a href=&quot;https://jquery.com/&quot;&gt;JQuery&lt;/a&gt;. Знакомы? Ну, значит точно объяснять ничего не надо!) Единственное что пришлось учесть при разработке: класс `Vox` работает с &lt;span title=&quot;Интерфейс пользователя, графический&quot;&gt;UI&lt;/span&gt; 3D-Coat, поэтому представленные в коде Vox-методы выделяют слои &lt;b&gt;прежде&lt;/b&gt; чем что-то с ними делать. Понимая это и порисовав в Коуте (&lt;a href=&quot;http://3d-coat.com/download/stable-release/&quot;&gt;бесплатно&lt;/a&gt; или &lt;a href=&quot;http://3d-coat.com/buy-now/&quot;&gt;нет&lt;/a&gt;), Вы не будете бомбардировать меня вопросами: &quot;&lt;i&gt;А зачем было создавать Root-методы!?&lt;/i&gt;&quot; К прочим вопросам открыт!&lt;br /&gt;
&lt;br /&gt;
Так, обход слоёв:&lt;br /&gt;
&lt;pre&gt;&lt;code class=&quot;c++&quot;&gt;void main() {

    // создание дерева - см. выше
    // ...

    // #1
    // проходим все слои и вызываем для каждого функцию invert()
    // см. ф. ниже
    v.forRootEach( &quot;invert&quot; );

    // #2
    // перемещаемся на слой &quot;Body&quot; и invert() для него и его деток
    v.to( &quot;Body&quot; ).call( &quot;invert&quot; ).forEach( &quot;invert&quot; );
}


// функция, о которой глаголилось выше
void invert() {
    Vox  v;
    v.isSurface() ? v.toVoxel() : v.toSurface();
    // добавил паузу, чтобы видеть движение в UI
    Wait( 50 );
}
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
Я считаю, что методов выше достаточно для обхода любого дерева. Но &lt;a href=&quot;https://facebook.com/andrew.shpagin&quot;&gt;Андрей Шпагин&lt;/a&gt; убеждает, что нет. Тогда вот ещё вариант:&lt;br /&gt;
&lt;pre&gt;&lt;code class=&quot;c++&quot;&gt;    // доступ по индексу для всех деток слоя &quot;Head&quot;
    v.to( &quot;Head&quot; ).call( &quot;invert&quot; );
    for ( int i = 0; i &amp;lt; v.count(); ++i ) {
        v.at( i ).call( &quot;invert&quot; ).parent();
        Wait( 100 );
    }
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
Также, из скриптов для класса `Vox` доступны &lt;b&gt;все&lt;/b&gt; возможности из меню, которое выпадает при щелчке правой кнопки мыши на слое:&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjXbjvatdESL1w3iKS-Ncht6zUwNcPKigiC4aXSsU8LWkK_8bVNCbb1by77TsgucWZKGM9BEzR8GTGLtIue17ezFb2izU4btR4j_nKphlEOycIzozer4q40cZ5neIoXQ52jzP7aYaan95Oj/s1600/surface.png&quot; /&gt;&lt;/div&gt;
&lt;br /&gt;
Что ещё хочу добавить, так это более лаконичный конструктор. Позже. Сейчас надо в скриптах поднять работу с примитивами, а их - ох как много... Вот буквально сегодня &lt;a href=&quot;https://facebook.com/vitaliy.volokh&quot;&gt;Виталик&lt;/a&gt; показывал горы болтов-шайб-гаек - ждите в новых версиях!&lt;br /&gt;
&lt;br /&gt;
P.S. Кстати, рассматриваемое дерево имеет &quot;живой прототип&quot;:&lt;br /&gt;
&lt;br /&gt;
&lt;iframe allowfullscreen=&quot;&quot; frameborder=&quot;0&quot; height=&quot;367&quot; mozallowfullscreen=&quot;true&quot; onmousewheel=&quot;&quot; src=&quot;https://sketchfab.com/models/91eb0eb061024bf1bc5e3eb5ffe385d8/embed&quot; webkitallowfullscreen=&quot;true&quot; width=&quot;619&quot;&gt;&lt;/iframe&gt;</content><link rel='replies' type='application/atom+xml' href='http://signmotion.blogspot.com/feeds/1169041022948452064/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2909062909816541374/1169041022948452064?isPopup=true' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2909062909816541374/posts/default/1169041022948452064'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2909062909816541374/posts/default/1169041022948452064'/><link rel='alternate' type='text/html' href='http://signmotion.blogspot.com/2015/11/volume-layers-script.html' title='Слои скриптами в SculptRoom'/><author><name>Andrii</name><uri>http://www.blogger.com/profile/02715216472597824596</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjcrHHkyfsW8m8HmZZeyd2fhzwEl-shXbCxnYVY_mVq7uJpe5QET9SerP_bCPeO4YEBlXJT44IRPOcL7VtgFJsDqXwfppdES-fdokbXX0-11jdBQAyipvURKBH3N-Wh2VCye2U-W4nsp6zPgNSyi7g6gFgmmo34dH_oL_FTXf31U65BXQ/s220/Andrey-400x.png'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEijurpWUh5pGoSh9pMUSH8SDuOiNDBqcTQHPmLo1jJbtnYN1V8Hw2Zdxd0Fyllud8mXXQGy_fG1I15yZMNdM6jwfsFJGwp2nmpiL4BJy92ddVdqyz5Ta-x8fZ7r2YIVSpgMOldscy-SS3Kw/s72-c/voxel-knight-3d-coat.jpg" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2909062909816541374.post-3365099889778302429</id><published>2015-11-03T19:00:00.000+02:00</published><updated>2016-02-24T10:10:52.669+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="3D-Coat"/><category scheme="http://www.blogger.com/atom/ns#" term="AngelScript"/><category scheme="http://www.blogger.com/atom/ns#" term="English"/><title type='text'>Figures draw figures</title><content type='html'>&lt;div class=&quot;img-desc&quot;&gt;&lt;img alt=&quot;3D-Coat AngelScript&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgDaw9qhZVEoIY7weRqqXENnzzgtiecz-QVJzK-gQ5ZucjIRFd9uN7ByXDAS3COmUxBUDrk-q_R_zu1JZ47h5aFT30nbFw0Ty34RPuAEC9uWX5rWJQVCP8sX9TF8XdsXXY_e1rB8ikEBYa2/s1600/spheres-figure.png&quot; /&gt;&lt;/div&gt;
&lt;div class=&quot;read-in&quot;&gt;&lt;a href=&quot;/2015/11/blog-post.html&quot; title=&quot;Фигуры рисуют фигуру&quot;&gt;&amp;sect; Читать по-русски &amp;rarr;&lt;/a&gt;&lt;/div&gt;

This post I wrote quickly. Quickly, because I wanted to understand what format is the best for examples. With each new post I will try to provide such format that will be most useful for you. Your feedback would be welcomed! In general, I want each example to not only show the &lt;b&gt;principles of scripting&lt;/b&gt; in 3D-Coat, but also show a &lt;b&gt;proper method&lt;/b&gt; for working with AngelScript (the AngelScript is used in &lt;a href=&quot;http://angelcode.com/angelscript/users.html&quot; target=&quot;_blank&quot;&gt;many areas&lt;/a&gt; – so it might be helpful). Thus, from my posts there will be a kind of “set of blanks” which you could use in your workflow or just for fun.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;What is going on here&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Making unusual structure using 3D-Coat&#39;s scripts. In other words, a 3D-plot. You &lt;b&gt;can change function and restart&lt;/b&gt; script to get &lt;a href=&quot;http://functionspace.com/topic/3051/Interesting-3d-shapes&quot; target=&quot;_blank&quot;&gt;something&lt;/a&gt; more interesting.&lt;/li&gt;
&lt;/ul&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;h3&gt;What can we learn from the code&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;How to clear the scene?&lt;/li&gt;
&lt;li&gt;How to toggle Voxels / Surface mode?&lt;/li&gt;
&lt;li&gt;How to create a 3D-model (&lt;a href=&quot;https://en.wikipedia.org/wiki/Polygon_mesh&quot; target=&quot;_blank&quot;&gt;&lt;i&gt;mesh&lt;/i&gt;&lt;/a&gt;)?&lt;/li&gt;
&lt;li&gt;How to add a sphere to a separate layer?&lt;/li&gt;
&lt;li&gt;How to place object to a certain location with defined coordinates?&lt;/li&gt;
&lt;li&gt;How to create 3D-plots?&lt;/li&gt;
&lt;li&gt;How to use `for-cycles`?&lt;/li&gt;
&lt;li&gt;What math functions are represented in AngelScript?&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;h3&gt;Code (3DCoat, AngelScript)&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;c++&quot;&gt;void main() {

    // preparing a scene
    SculptRoom  room;
    room.clear().toSurface();

    // building some structure with spheres
    Builder  builder;
    const int  IU = 4;
    const int  ITHETA = 3;
    const float  S = 5.0;
    const float  PI = 3.14159;
    for ( int iu = -IU; iu &lt;= IU; ++iu ) {
        for ( int itheta = 0; itheta &lt;= ITHETA; ++itheta ) {
            const float  u = 1.0 * iu / IU;
            const float  theta = 2.0 * PI * itheta / ITHETA;
            const float  x = sqrt( 1.0 - u * u ) * cos( theta );
            const float  y = sqrt( 1.0 - u * u ) * sin( theta );
            const float  z = u;
            const float  radius = (itheta + u * u) * S + 1;
            const Vec3  coord = Vec3( x, y, z ) * radius * 1.7 * S;
            const Mesh  figure = builder.sphere()
              .radius( radius )
              .position( coord )
              .details( 0.1 )
              ();
            room |= figure;
        } // itheta
    } // iu
}
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
&lt;h3&gt;Result&lt;/h3&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbq6LupScvvUi2F6_Tkcy7coUtk2lxOZH_uS1ecWxgMCa4lgU6o4WCGwJbiWQ5Mk_zsIWJePWihsoHsTbBuiLyE0fMZU8AuIM2kyJYxEjcYD_amv9c2kyFPeBbLwgvX9qU_P1aIm0kRIRj/s1600/spheres-figure.jpg&quot; imageanchor=&quot;1&quot; style=&quot;clear: left; float: left; margin-bottom: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbq6LupScvvUi2F6_Tkcy7coUtk2lxOZH_uS1ecWxgMCa4lgU6o4WCGwJbiWQ5Mk_zsIWJePWihsoHsTbBuiLyE0fMZU8AuIM2kyJYxEjcYD_amv9c2kyFPeBbLwgvX9qU_P1aIm0kRIRj/s1600/spheres-figure.jpg&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;Your questions?&lt;/h3&gt;
</content><link rel='replies' type='application/atom+xml' href='http://signmotion.blogspot.com/feeds/3365099889778302429/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2909062909816541374/3365099889778302429?isPopup=true' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2909062909816541374/posts/default/3365099889778302429'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2909062909816541374/posts/default/3365099889778302429'/><link rel='alternate' type='text/html' href='http://signmotion.blogspot.com/2015/11/draw-plots-scripting-3dcoat.html' title='Figures draw figures'/><author><name>Andrii</name><uri>http://www.blogger.com/profile/02715216472597824596</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjcrHHkyfsW8m8HmZZeyd2fhzwEl-shXbCxnYVY_mVq7uJpe5QET9SerP_bCPeO4YEBlXJT44IRPOcL7VtgFJsDqXwfppdES-fdokbXX0-11jdBQAyipvURKBH3N-Wh2VCye2U-W4nsp6zPgNSyi7g6gFgmmo34dH_oL_FTXf31U65BXQ/s220/Andrey-400x.png'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgDaw9qhZVEoIY7weRqqXENnzzgtiecz-QVJzK-gQ5ZucjIRFd9uN7ByXDAS3COmUxBUDrk-q_R_zu1JZ47h5aFT30nbFw0Ty34RPuAEC9uWX5rWJQVCP8sX9TF8XdsXXY_e1rB8ikEBYa2/s72-c/spheres-figure.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2909062909816541374.post-7649780024911638663</id><published>2015-11-03T18:10:00.000+02:00</published><updated>2016-02-24T10:11:53.729+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="3D-Coat"/><category scheme="http://www.blogger.com/atom/ns#" term="AngelScript"/><category scheme="http://www.blogger.com/atom/ns#" term="Russian"/><title type='text'>Фигуры рисуют фигуру</title><content type='html'>&lt;div class=&quot;img-desc&quot;&gt;&lt;img alt=&quot;3D-Coat AngelScript&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgDaw9qhZVEoIY7weRqqXENnzzgtiecz-QVJzK-gQ5ZucjIRFd9uN7ByXDAS3COmUxBUDrk-q_R_zu1JZ47h5aFT30nbFw0Ty34RPuAEC9uWX5rWJQVCP8sX9TF8XdsXXY_e1rB8ikEBYa2/s1600/spheres-figure.png&quot; /&gt;&lt;/div&gt;
&lt;div class=&quot;read-in&quot;&gt;&lt;a href=&quot;/2015/11/draw-plots-scripting-3dcoat.html&quot; title=&quot;Figures draw figures&quot;&gt;&amp;sect; Read in English &amp;rarr;&lt;/a&gt;&lt;/div&gt;

Эту заметку я написал быстро. Быстро, потому что хочу определить, в каком виде подавать примеры. С каждой новой публикацией буду подводить оформление к виду, который принесёт Вам наибольшую пользу. Обратная связь была бы кстати! Вообще, я хочу, чтобы каждый пример не просто раскрывал &lt;b&gt;принципы скриптования&lt;/b&gt; в 3D-Coat, но и обучал &lt;b&gt;грамотной работе&lt;/b&gt; с AngelScript (AS много где &lt;a href=&quot;http://angelcode.com/angelscript/users.html&quot; target=&quot;_blank&quot;&gt;применяется&lt;/a&gt; - наверняка пригодится). Т.о. из публикаций получится некий &quot;набор заготовок&quot;, которые Вы сможете использовать в работе... или для развлечения.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Что здесь происходит&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;С помощью скрипта 3D-Сoat рисуем необычную структуру. Другими словами, &quot;график в 3D&quot;. Вы можете менять функцию и &lt;b&gt;тут же&lt;/b&gt; перезапускать скрипт, чтобы получить &lt;a href=&quot;http://functionspace.com/topic/3051/Interesting-3d-shapes&quot; target=&quot;_blank&quot;&gt;что-то&lt;/a&gt; более интересное.&lt;/li&gt;
&lt;/ul&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;h3&gt;
Чему учит код&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Как очистить сцену?&lt;/li&gt;
&lt;li&gt;Как переключать режимы сцены: воксель / поверхность?&lt;/li&gt;
&lt;li&gt;Как создать 3D-модель (&lt;a href=&quot;https://ru.wikipedia.org/wiki/%D0%9F%D0%BE%D0%BB%D0%B8%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D1%81%D0%B5%D1%82%D0%BA%D0%B0&quot; target=&quot;_blank&quot;&gt;&lt;i&gt;меш&lt;/i&gt;&lt;/a&gt;)?&lt;/li&gt;
&lt;li&gt;Как добавить сферу в отдельный слой?&lt;/li&gt;
&lt;li&gt;Как разместить фигуру по заданным координатам?&lt;/li&gt;
&lt;li&gt;Как строить объёмные графики?&lt;/li&gt;
&lt;li&gt;Как использовать `for-циклы`?&lt;/li&gt;
&lt;li&gt;Какие математические функции предоставляет AngelScript?&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;h3&gt;Код (3DCoat, AngelScript)&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;c++&quot;&gt;// Модель, заданная функцией на 3D-холсте.
void main() {

    // подготавливаем сцену
    SculptRoom  room;
    room.clear().toSurface();

    // строим некую 3D-структуру
    Builder  builder;
    const int  IU = 4;
    const int  ITHETA = 3;
    const float  S = 5.0;
    const float  PI = 3.14159;
    for ( int iu = -IU; iu &lt;= IU; ++iu ) {
        for ( int itheta = 0; itheta &lt;= ITHETA; ++itheta ) {
            const float  u = 1.0 * iu / IU;
            const float  theta = 2.0 * PI * itheta / ITHETA;
            const float  x = sqrt( 1.0 - u * u ) * cos( theta );
            const float  y = sqrt( 1.0 - u * u ) * sin( theta );
            const float  z = u;
            const float  radius = (itheta + u * u) * S + 1;
            const Vec3  coord = Vec3( x, y, z ) * radius * 1.7 * S;
            const Mesh  figure = builder.sphere()
              .radius( radius )
              .position( coord )
              .details( 0.1 )
              ();
            room |= figure;
        } // itheta
    } // iu
}
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
&lt;h3&gt;
Результат&lt;/h3&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbq6LupScvvUi2F6_Tkcy7coUtk2lxOZH_uS1ecWxgMCa4lgU6o4WCGwJbiWQ5Mk_zsIWJePWihsoHsTbBuiLyE0fMZU8AuIM2kyJYxEjcYD_amv9c2kyFPeBbLwgvX9qU_P1aIm0kRIRj/s1600/spheres-figure.jpg&quot; imageanchor=&quot;1&quot; style=&quot;clear: left; float: left; margin-bottom: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbq6LupScvvUi2F6_Tkcy7coUtk2lxOZH_uS1ecWxgMCa4lgU6o4WCGwJbiWQ5Mk_zsIWJePWihsoHsTbBuiLyE0fMZU8AuIM2kyJYxEjcYD_amv9c2kyFPeBbLwgvX9qU_P1aIm0kRIRj/s1600/spheres-figure.jpg&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Ваши вопросы? (задавайте в комментариях)&lt;/h3&gt;</content><link rel='replies' type='application/atom+xml' href='http://signmotion.blogspot.com/feeds/7649780024911638663/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2909062909816541374/7649780024911638663?isPopup=true' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2909062909816541374/posts/default/7649780024911638663'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2909062909816541374/posts/default/7649780024911638663'/><link rel='alternate' type='text/html' href='http://signmotion.blogspot.com/2015/11/blog-post.html' title='Фигуры рисуют фигуру'/><author><name>Andrii</name><uri>http://www.blogger.com/profile/02715216472597824596</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjcrHHkyfsW8m8HmZZeyd2fhzwEl-shXbCxnYVY_mVq7uJpe5QET9SerP_bCPeO4YEBlXJT44IRPOcL7VtgFJsDqXwfppdES-fdokbXX0-11jdBQAyipvURKBH3N-Wh2VCye2U-W4nsp6zPgNSyi7g6gFgmmo34dH_oL_FTXf31U65BXQ/s220/Andrey-400x.png'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgDaw9qhZVEoIY7weRqqXENnzzgtiecz-QVJzK-gQ5ZucjIRFd9uN7ByXDAS3COmUxBUDrk-q_R_zu1JZ47h5aFT30nbFw0Ty34RPuAEC9uWX5rWJQVCP8sX9TF8XdsXXY_e1rB8ikEBYa2/s72-c/spheres-figure.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2909062909816541374.post-6950816786042127527</id><published>2015-11-02T19:00:00.000+02:00</published><updated>2016-02-24T10:12:49.092+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="3D-Coat"/><category scheme="http://www.blogger.com/atom/ns#" term="AngelScript"/><category scheme="http://www.blogger.com/atom/ns#" term="English"/><title type='text'>Scripts in 3D-Coat: Beginning</title><content type='html'>&lt;div class=&quot;img-desc&quot;&gt;&lt;img alt=&quot;3D-Coat AngelScript&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhUCt_fw7si56ZPIRmT5hzXoAo2X-CwVHAVdGDnoWRMCdzTOsbmSPZXv8cOYMO_5du2XlHlwrhWg3YFhgP4a0gZhJeKwTlMDQaJVsZj5rtFtC2s46vSAmYvj4TNy9tdfRWVShMsfNs1HMpq/s1600/3d-coat-angelscript.png&quot; /&gt;&lt;cite&gt;@&lt;a href=&quot;http://vk.com/3dcoat&quot;&gt;Group VK&lt;/a&gt;&lt;/cite&gt;&lt;/div&gt;
&lt;div class=&quot;read-in&quot;&gt;&lt;a href=&quot;/2015/11/3d-coat.html&quot; title=&quot;Скрипты 3D-Coat: Начало&quot;&gt;&amp;sect; Читать по-русски &amp;rarr;&lt;/a&gt;&lt;/div&gt;

Right now I&#39;m working on Scripts/Scripting in &lt;a href=&quot;http://3d-coat.com/&quot;&gt;3D-Coat&lt;/a&gt; (appeared classes &#39;Angles&#39;, &#39;Mat3&#39;, &#39;Mat4&#39;, &#39;Mesh&#39;, &#39;Quat&#39;,  &#39;Vec3&#39;) and decided to, in addition to &lt;a href=&quot;http://j.mp/3dc-angelscript&quot;&gt;documentation&lt;/a&gt;, create more visual examples. I&#39;ll start here – we&#39;ll see what will happen...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;
&lt;b&gt;Introduction for new users&lt;/b&gt;&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;3D-Coat is a software for creating 3d models/sculptings, particular organic objects (for more information visit &lt;a href=&quot;http://3d-coat.com/&quot; target=&quot;_blank&quot;&gt;website&lt;/a&gt;). Here you also have retopology toolset, including Auto-retopology of voxel objects (&lt;a href=&quot;https://youtu.be/fh8qAVkXzlI&quot; target=&quot;_blank&quot;&gt;video&lt;/a&gt;), plus PBR (&lt;a href=&quot;https://youtu.be/_fb5tHXpCPs&quot; target=&quot;_blank&quot;&gt;video&lt;/a&gt;), plus UV mapping tools (&lt;a href=&quot;http://lesterbanks.com/2012/12/why-3dcoat-is-an-amazing-uv-mapping-tool/&quot; target=&quot;_blank&quot;&gt;video&lt;/a&gt;), exporting models for game engines, and many more... Yep, I love this program!)&lt;/li&gt;
&lt;li&gt;I assume you know a programming language and know how to use documentation.&lt;/li&gt;
&lt;li&gt;3D-Coat uses &lt;a href=&quot;https://ru.wikipedia.org/wiki/AngelScript&quot; target=&quot;_blank&quot;&gt;AngelScript&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Script is a text file. It is helpful to view and edit it in &lt;a href=&quot;https://notepad-plus-plus.org/&quot; target=&quot;_blank&quot;&gt;Notepad++&lt;/a&gt; (choose &quot;&lt;i&gt;C&lt;/i&gt;&quot; syntax).&lt;/li&gt;
&lt;li&gt;Run script via file menu &quot;&lt;i&gt;Scripts / Run Script&lt;/i&gt;&quot;.&lt;/li&gt;
&lt;li&gt;Free download the 3D-Coat is &lt;a href=&quot;http://3d-coat.com/&quot; target=&quot;_blank&quot;&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;b&gt;and some accordances for me (like memo)&lt;/b&gt;&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Short, but informative posts.&lt;/li&gt;
&lt;li&gt;Simple code.&lt;/li&gt;
&lt;li&gt;Comments inside the code.&lt;/li&gt;
&lt;li&gt;Won&#39;t spoon-feed you with anything that can otherwise &lt;a href=&quot;http://j.mp/3dc-angelscript&quot; target=&quot;_blank&quot;&gt;be found in documentation&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;For each post – a picture / video / 3D-sketch.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
I will maintain these rules. Have questions? Ask – the answer will be  given )&lt;br /&gt;
&lt;br /&gt;
First example is adding figures to a scene in &quot;&lt;i&gt;Sculpt Room&lt;/i&gt;&quot; (according to 3D-Coat&#39;s terminology).&lt;br /&gt;
&lt;ul&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;c++&quot;&gt;void main() {

    // preparing a scene
    SculptRoom  room;
    room.clear().toSurface();

    // initializing a random generator
    seed( 39 );

    // building some figures with random size, position and rotation
    Builder  builder;
    const int  N = 4;
    const int  A = 10;
    const int  B = 100;
    for ( int i = 0; i &lt; N; ++i ) {
        const int  a = rand( A, B );
        const int  b = rand( A, B );
        const int  c = rand( A, B );
        Mesh  figure = builder.cube()
          .side( Vec3( a, b, c ) )
          .details( 0.1 )
          ();
        const Vec3  translation(
            rand( -B, B ) * 2,
            rand( -B, B ) * 2,
            rand( -B, B ) * 2);
        const Angles  angles(
            rand( 0, 360 ),
            rand( 0, 360 ),
            rand( 0, 360 ) );
        figure.tools().transform()
          .position( translation )
          .rotation( angles )
          ();
        room |= figure;
    } // for i
}&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
&lt;h3&gt;Result&lt;/h3&gt;
LMB - rotate, RMB - pan, MMB - zoom.&lt;br /&gt;
&lt;br /&gt;
&lt;iframe allowfullscreen=&quot;&quot; frameborder=&quot;0&quot; height=&quot;367&quot; mozallowfullscreen=&quot;true&quot; onmousewheel=&quot;&quot; src=&quot;https://sketchfab.com/models/4bd3363f08614ae8bd90739f6d9532b8/embed&quot; webkitallowfullscreen=&quot;true&quot; width=&quot;619&quot;&gt;&lt;/iframe&gt;
</content><link rel='replies' type='application/atom+xml' href='http://signmotion.blogspot.com/feeds/6950816786042127527/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2909062909816541374/6950816786042127527?isPopup=true' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2909062909816541374/posts/default/6950816786042127527'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2909062909816541374/posts/default/6950816786042127527'/><link rel='alternate' type='text/html' href='http://signmotion.blogspot.com/2015/11/scripts-3dcoat-beginning.html' title='Scripts in 3D-Coat: Beginning'/><author><name>Andrii</name><uri>http://www.blogger.com/profile/02715216472597824596</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjcrHHkyfsW8m8HmZZeyd2fhzwEl-shXbCxnYVY_mVq7uJpe5QET9SerP_bCPeO4YEBlXJT44IRPOcL7VtgFJsDqXwfppdES-fdokbXX0-11jdBQAyipvURKBH3N-Wh2VCye2U-W4nsp6zPgNSyi7g6gFgmmo34dH_oL_FTXf31U65BXQ/s220/Andrey-400x.png'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhUCt_fw7si56ZPIRmT5hzXoAo2X-CwVHAVdGDnoWRMCdzTOsbmSPZXv8cOYMO_5du2XlHlwrhWg3YFhgP4a0gZhJeKwTlMDQaJVsZj5rtFtC2s46vSAmYvj4TNy9tdfRWVShMsfNs1HMpq/s72-c/3d-coat-angelscript.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2909062909816541374.post-1837757296335384078</id><published>2015-11-02T13:54:00.000+02:00</published><updated>2016-02-24T10:13:32.085+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="3D-Coat"/><category scheme="http://www.blogger.com/atom/ns#" term="AngelScript"/><category scheme="http://www.blogger.com/atom/ns#" term="Russian"/><title type='text'>Скрипты 3D-Coat: Начало</title><content type='html'>&lt;div class=&quot;img-desc&quot;&gt;&lt;img alt=&quot;3D-Coat AngelScript&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhUCt_fw7si56ZPIRmT5hzXoAo2X-CwVHAVdGDnoWRMCdzTOsbmSPZXv8cOYMO_5du2XlHlwrhWg3YFhgP4a0gZhJeKwTlMDQaJVsZj5rtFtC2s46vSAmYvj4TNy9tdfRWVShMsfNs1HMpq/s1600/3d-coat-angelscript.png&quot; /&gt;&lt;cite&gt;@&lt;a href=&quot;http://vk.com/3dcoat&quot;&gt;Группа ВК&lt;/a&gt;&lt;/cite&gt;&lt;/div&gt;
&lt;div class=&quot;read-in&quot;&gt;&lt;a href=&quot;/2015/11/scripts-3dcoat-beginning.html&quot; title=&quot;Scripts in 3D-Coat: Beginning&quot;&gt;&amp;sect; Read in English &amp;rarr;&lt;/a&gt;&lt;/div&gt;

Сейчас работаю над скриптами &lt;a href=&quot;http://3d-coat.com/&quot;&gt;3D-Coat&lt;/a&gt; (появились классы `Angles`, `Mat3`, `Mat4`, `Mesh`, `Quat`, `Vec3`) и решил, в дополнение к &lt;a href=&quot;http://j.mp/3dc-angelscript&quot;&gt;документации&lt;/a&gt;, создать более наглядные примеры. Начну здесь, посмотрим, что из этого получится...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;
&lt;b&gt;Вводные моменты для новых читателей&lt;/b&gt;&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;3D-Coat - это инструмент для создания 3D-моделей, в частности органических объектов (см. &lt;a href=&quot;http://3d-coat.com/&quot; target=&quot;_blank&quot;&gt;сайт&lt;/a&gt;). Плюс автоматическая ретопология воксельных объектов (см. &lt;a href=&quot;https://youtu.be/fh8qAVkXzlI&quot; target=&quot;_blank&quot;&gt;видео&lt;/a&gt;), плюс PBR (&lt;a href=&quot;https://youtu.be/_fb5tHXpCPs&quot; target=&quot;_blank&quot;&gt;видео&lt;/a&gt;), плюс UV-развёртка (&lt;a href=&quot;http://lesterbanks.com/2012/12/why-3dcoat-is-an-amazing-uv-mapping-tool/&quot; target=&quot;_blank&quot;&gt;видео&lt;/a&gt;), плюс рельефное текстурирование, плюс экспорт моделей для игровых движков... Да, я люблю эту программу!)&lt;/li&gt;
&lt;li&gt;Полагаю, что Вы знаете какой-то язык программирования и умеете пользоваться документацией. &lt;/li&gt;
&lt;li&gt;3D-Coat понимает &lt;a href=&quot;https://ru.wikipedia.org/wiki/AngelScript&quot; target=&quot;_blank&quot;&gt;AngelScript&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Скрипт - это текстовый файл. Удобно создавать и просматривать в &lt;a href=&quot;https://notepad-plus-plus.org/&quot; target=&quot;_blank&quot;&gt;Notepad++&lt;/a&gt;, с подсветкой синтаксиса &quot;&lt;i&gt;C&lt;/i&gt;&quot;. &lt;/li&gt;
&lt;li&gt;Запуск скрипта - из меню 3D-Coat &quot;&lt;i&gt;Скрипты / Запустить скрипт&lt;/i&gt;&quot;:&amp;nbsp;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEglh8yKoMJuDhSV5UN5bo-GFHOaGNp9UqW5xmqRhzvrFnVsq4swbKDZi-0oN6kB64RCI2OID9PoPohz_WPuLsXrA-EjCDTbP6GjwnNjgBL9rxoLZcKcemsklWTmvbHTD-n5IA5sBybWAXOV/s1600/3d-coat-menu-script.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEglh8yKoMJuDhSV5UN5bo-GFHOaGNp9UqW5xmqRhzvrFnVsq4swbKDZi-0oN6kB64RCI2OID9PoPohz_WPuLsXrA-EjCDTbP6GjwnNjgBL9rxoLZcKcemsklWTmvbHTD-n5IA5sBybWAXOV/s1600/3d-coat-menu-script.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;Бесплатно скачать 3D-Coat можно &lt;a href=&quot;http://3d-coat.com/&quot; target=&quot;_blank&quot;&gt;отсюда&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;b&gt;и соглашения для себя (чтобы помнить) &lt;/b&gt;&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Краткие, но ёмкие публикации.&lt;/li&gt;
&lt;li&gt;Простой код. &lt;/li&gt;
&lt;li&gt;Комментарии в самом коде.&lt;/li&gt;
&lt;li&gt;Не разжёвывать методы, которые можно &lt;a href=&quot;http://j.mp/3dc-angelscript&quot; target=&quot;_blank&quot;&gt;найти в документации&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Для каждой публикации - картинка / видео / 3D-Sketch.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
Буду придерживаться этих правил. Если возникнуть вопросы - задавайте, ответ будет) &lt;br /&gt;
&lt;br /&gt;
Первый пример - это добавление фигур &quot;на сцену&quot; или, согласно терминологии 3D-Coat, в &quot;&lt;i&gt;Voxel Room&lt;/i&gt;&quot; (здесь и далее используются термины из &lt;a href=&quot;http://3d-coat.com/files/manual_4.0.pdf&quot; target=&quot;_blank&quot;&gt;руководства&lt;/a&gt;).&lt;br /&gt;
&lt;ul&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;c++&quot;&gt;// Фигуры, разбросанные по сцене.
void main() {

    // подготавливаем сцену
    SculptRoom  room;
    room.clear().toSurface();

    // инициализируем генератор случ. чисел
    seed( 39 );

    // создаём `N` фигур разного размера, разбрасывая их по сцене
    Builder  builder;
    const int  N = 4;
    const int  A = 10;
    const int  B = 100;
    for ( int i = 0; i &lt; N; ++i ) {
        const int  a = rand( A, B );
        const int  b = rand( A, B );
        const int  c = rand( A, B );
        Mesh  figure = builder.cube()
          .side( Vec3( a, b, c ) )
          .details( 0.1 )
          ();
        const Vec3  translation(
            rand( -B, B ) * 2,
            rand( -B, B ) * 2,
            rand( -B, B ) * 2);
        const Angles  angles(
            rand( 0, 360 ),
            rand( 0, 360 ),
            rand( 0, 360 ) );
        figure.tools().transform()
          .position( translation )
          .rotation( angles )
          ();
        room |= figure;
    } // for i
}&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
&lt;h3&gt;Результат&lt;/h3&gt;
Правая / левая / средняя кнопки мыши - двигайте / вращайте / масштабируйте.&lt;br /&gt;
&lt;br /&gt;
&lt;iframe allowfullscreen=&quot;&quot; frameborder=&quot;0&quot; height=&quot;367&quot; mozallowfullscreen=&quot;true&quot; onmousewheel=&quot;&quot; src=&quot;https://sketchfab.com/models/4bd3363f08614ae8bd90739f6d9532b8/embed&quot; webkitallowfullscreen=&quot;true&quot; width=&quot;619&quot;&gt;&lt;/iframe&gt;</content><link rel='replies' type='application/atom+xml' href='http://signmotion.blogspot.com/feeds/1837757296335384078/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2909062909816541374/1837757296335384078?isPopup=true' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2909062909816541374/posts/default/1837757296335384078'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2909062909816541374/posts/default/1837757296335384078'/><link rel='alternate' type='text/html' href='http://signmotion.blogspot.com/2015/11/3d-coat.html' title='Скрипты 3D-Coat: Начало'/><author><name>Andrii</name><uri>http://www.blogger.com/profile/02715216472597824596</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjcrHHkyfsW8m8HmZZeyd2fhzwEl-shXbCxnYVY_mVq7uJpe5QET9SerP_bCPeO4YEBlXJT44IRPOcL7VtgFJsDqXwfppdES-fdokbXX0-11jdBQAyipvURKBH3N-Wh2VCye2U-W4nsp6zPgNSyi7g6gFgmmo34dH_oL_FTXf31U65BXQ/s220/Andrey-400x.png'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhUCt_fw7si56ZPIRmT5hzXoAo2X-CwVHAVdGDnoWRMCdzTOsbmSPZXv8cOYMO_5du2XlHlwrhWg3YFhgP4a0gZhJeKwTlMDQaJVsZj5rtFtC2s46vSAmYvj4TNy9tdfRWVShMsfNs1HMpq/s72-c/3d-coat-angelscript.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2909062909816541374.post-1972342673786857535</id><published>2013-01-29T15:57:00.000+02:00</published><updated>2015-11-03T18:40:58.355+02:00</updated><title type='text'>Подсветка синтаксиса Graphviz для Notepad++</title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: left; float: left; margin-bottom: 1em; margin-right: 2em; text-align: left;&quot;&gt;
&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhaFbqj_FcuAWK7Og7C9cX8Sm49e1fVdV1Gi-xR738QzOns67KLe_kTethoKlfhwUG49pWpST61HVQbfRyVa1eX9S0P-tIhMuc3So507lZzRGGRIJhgEN34bKThwAK8AXMPVgCc2t1-CGSZ/s400/graphviz-syntax-highlighting-notepad.png&quot; /&gt;&lt;/div&gt;
&lt;br /&gt;
Был несколько удивлён, когда не нашёл в Интернете подсветку синтаксиса &lt;a href=&quot;http://graphviz.org/&quot;&gt;Graphviz&lt;/a&gt; для &lt;a href=&quot;http://notepad-plus-plus.org/&quot;&gt;Notepad++&lt;/a&gt;. Формально она как бы &lt;a href=&quot;http://blog.antiblau.de/wp-content/uploads/userDefineLang.zip&quot;&gt;есть&lt;/a&gt;, но сайт, на который ссылается &lt;a href=&quot;https://sourceforge.net/apps/mediawiki/notepad-plus/index.php?title=User_Defined_Language_Files&quot;&gt;NpWiki&lt;/a&gt; недоступен уже очень давно.&lt;br /&gt;
&lt;br /&gt;
Помимо стандартного dot-синтаксиса подсветка выделяет полезные для больших проектов директивы &#39;&lt;i&gt;@todo&lt;/i&gt;&#39;.&lt;br /&gt;
&lt;br /&gt;
&lt;a href=&quot;https://github.com/signmotion/graphviz-syntax-highlighting&quot; target=&quot;_blank&quot;&gt;Пользуйтесь на здоровье &amp;gt;&amp;gt;&lt;/a&gt;&lt;br /&gt;
&amp;nbsp;
</content><link rel='replies' type='application/atom+xml' href='http://signmotion.blogspot.com/feeds/1972342673786857535/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2909062909816541374/1972342673786857535?isPopup=true' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2909062909816541374/posts/default/1972342673786857535'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2909062909816541374/posts/default/1972342673786857535'/><link rel='alternate' type='text/html' href='http://signmotion.blogspot.com/2013/01/graphviz-notepad.html' title='Подсветка синтаксиса Graphviz для Notepad++'/><author><name>Andrii</name><uri>http://www.blogger.com/profile/02715216472597824596</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjcrHHkyfsW8m8HmZZeyd2fhzwEl-shXbCxnYVY_mVq7uJpe5QET9SerP_bCPeO4YEBlXJT44IRPOcL7VtgFJsDqXwfppdES-fdokbXX0-11jdBQAyipvURKBH3N-Wh2VCye2U-W4nsp6zPgNSyi7g6gFgmmo34dH_oL_FTXf31U65BXQ/s220/Andrey-400x.png'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhaFbqj_FcuAWK7Og7C9cX8Sm49e1fVdV1Gi-xR738QzOns67KLe_kTethoKlfhwUG49pWpST61HVQbfRyVa1eX9S0P-tIhMuc3So507lZzRGGRIJhgEN34bKThwAK8AXMPVgCc2t1-CGSZ/s72-c/graphviz-syntax-highlighting-notepad.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2909062909816541374.post-1903649280342967022</id><published>2012-06-30T18:43:00.001+03:00</published><updated>2015-11-03T18:39:40.996+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="CouchDB"/><title type='text'>Чего не хватает в NoSQL-хранилищах (на примере CouchDB) - Часть III</title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: left; float: left; margin-bottom: 1em; margin-right: 2em; text-align: left;&quot;&gt;
&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhoXkiU8W_6RFtDMka5wSv1dsnPJjuOfMmyWs2AW30aLXcLNWtJwS8PHYrcdk_1i9ytEFpoqJPZYW0UAZyUEk1ms6ycluWOK4_IbZCoRaEH4adSMQOrp_ao5-0fyoeRf5kdVfMW_QU9B6Ar/s1600/nosql-bi-couchdb-bigdata-3.png&quot; /&gt;&lt;/div&gt;
Продолжение. Начало &amp;gt; &quot;Чего не хватает в NoSQL-хранилищах&quot;: &lt;a href=&quot;http://signmotion.blogspot.com/2012/05/nosql-couchdb.html&quot;&gt;Часть I&lt;/a&gt;, &lt;a href=&quot;http://signmotion.blogspot.com/2012/05/nosql-couchdb-ii.html&quot;&gt;Часть II&lt;/a&gt;.&lt;br /&gt;
&lt;ol&gt;
&lt;li style=&quot;text-align: justify;&quot; value=&quot;11&quot;&gt;&lt;b&gt;Интерфейс для написания плагинов.&lt;/b&gt; Расширять функциональность самой CouchDB - можно. &lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEireLEPBWcZv0ejQmhhazBeUwWVhFU4WMsKp4b7l4cXsdFDxOqbRsVF9A6RPbfJq99QsB47RO3Yw28WBI6Gwnjmpb_c4n_R_vCT-L7j7ijOJU8GeEXC0tXgarCjTsO8oa3Yubrvxs8HgGnj/s1600/couchdb-extend-struct-api.png&quot; imageanchor=&quot;1&quot; style=&quot;clear: right; float: right; margin-bottom: 1em; margin-left: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;262&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEireLEPBWcZv0ejQmhhazBeUwWVhFU4WMsKp4b7l4cXsdFDxOqbRsVF9A6RPbfJq99QsB47RO3Yw28WBI6Gwnjmpb_c4n_R_vCT-L7j7ijOJU8GeEXC0tXgarCjTsO8oa3Yubrvxs8HgGnj/s400/couchdb-extend-struct-api.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt; Об этом &lt;a href=&quot;http://davispj.com/2010/09/26/new-couchdb-externals-api.html&quot;&gt;говорилось&lt;/a&gt; ещё в 2010 году и в документации есть парочка рабочих &lt;a href=&quot;http://wiki.apache.org/couchdb/ExternalProcesses&quot;&gt;примеров&lt;/a&gt;. Можно, но... делать это - отвратительно! (Конечно, если Вы не гик и можете позволить себе жить процессом, а не результатом). Мне было не просто отладить свой плагин, лопативший базы и объединяющий их записи по определённым условиям: создавал его на JavaScript (под движок или SpiderMonkey или V8). Тем не менее, &lt;a href=&quot;https://scoutapp.com/plugin_urls/441-couchdb-overall&quot;&gt;Scout&lt;/a&gt;, &lt;a href=&quot;http://www.elasticsearch.org/&quot;&gt;ElasticSearch&lt;/a&gt;, &lt;a href=&quot;https://github.com/rnewson/couchdb-lucene/&quot;&gt;Lucene&lt;/a&gt;, &lt;a href=&quot;http://janmonschke.com/projects/backbone-couchdb.html&quot;&gt;BackBone&lt;/a&gt; и &lt;a href=&quot;http://daleharvey.github.com/jquery.couch.js-docs/symbols/index.html&quot;&gt;$.Couch&lt;/a&gt; (последняя пара - не совсем плагины, но очень полезные библиотеки) - показатели того, что создавать плагины можно. Этому способствует такой вот API (да, эта картинка).&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Предметно-ориентированный язык программирования&lt;/b&gt; для создания индексов, функций проверки и т.п.. Это что-то вроде&amp;nbsp; SQL. Хм... Для прикладных задач вполне годится JavaScript (или &lt;a href=&quot;https://issues.apache.org/jira/browse/COUCHDB-817&quot;&gt;CoffeeScript&lt;/a&gt; - для ярых эстетов). Зачем усложнять? Впрочем, можно привести много причин &quot;зачем&quot;...&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Гибкая система разрешения конфликтов документов&lt;/b&gt;. Репликация - большая головня боль для разработчиков SQL-систем. NoSQL позволяет разработчикам сосредоточиться на задаче, взяв на себя большую часть сложностей репликации. Но отдавать роботам решать всё за нас - это не правильно (пока процесс не отлажен). Например, при репликации бывают моменты, когда документ изменён одновременно несколькими пользователями и каждый желает записать свои изменения в хранилище. Хотелось бы иметь что-то более настраиваемое, чем просто &quot;получить список конфликтующих документов и выбрать вручную нужный&quot;.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Хранение прикреплённых файлов вне базы&lt;/b&gt;. CouchDB хранит свои данные в одном файле. Этот файл при работе с базой &lt;i&gt;никогда не становится меньше&lt;/i&gt; , данные &lt;i&gt;никогда не перезаписываются&lt;/i&gt; (Вы можете только настроить периодическое сжатие файла). Это делает CouchDB очень надёжным хранилищем, но прикреплённые файлы сильно портят картину, т.к. при каждом обновлении документа, делается их полная копия... Да, места может потребоваться много. Это решается частичным обновлением документа (которого пока нет). Хранить файлы вне базы добавит сложностей в администрировании, но, видимо, есть задачи, когда без этого не обойтись: ведь этот пункт далеко не в конце &lt;a href=&quot;http://www.allourideas.org/couchdb2012/results?more=true&quot;&gt;списка необходимого в NoSQL&lt;/a&gt;. &lt;/li&gt;
&lt;li&gt;&lt;div class=&quot;line&quot; id=&quot;LC179&quot;&gt;
&lt;b&gt;Определение целостности базы и восстановление в случае сбоев&lt;/b&gt;. Здесь имеется ввиду собрать вместе утилиты для контроля целостности и организовать удобный интерфейс для работы с ними. Потому что само хранилище CouchDB по надёжности сопоставимо с файловой системой. У Вас часто повреждаются хранимые на диске офисные документы? (Надеюсь, нет; иначе - пора бы обновить компьютер). Вот, так же &quot;часто&quot; будет &quot;ломаться&quot; база CouchDB. Впрочем, и здесь есть куда расти. Например, добавить хранение информации для восстановления файла; контрольные суммы на документы, B-деревья, представления; утилиты, позволяющие &quot;распотрошить&quot; поломанный файл CouchDB и вытащить оттуда всё, что ещё можно вытащить. Если Вам нужна б&lt;i&gt;о&lt;/i&gt;льшая надёжность, подключайте кластеры с &lt;a href=&quot;https://github.com/cloudant/bigcouch&quot;&gt;BigCouch&lt;/a&gt; или посмотрите в сторону &lt;a href=&quot;http://couchbase.com/&quot;&gt;CouchBase&lt;/a&gt; - эти проекты &lt;a href=&quot;http://habrahabr.ru/post/135801/&quot;&gt;выросли из CouchDB&lt;/a&gt; и ориентированы на потребности бизнеса. &lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;br /&gt;
^</content><link rel='replies' type='application/atom+xml' href='http://signmotion.blogspot.com/feeds/1903649280342967022/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2909062909816541374/1903649280342967022?isPopup=true' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2909062909816541374/posts/default/1903649280342967022'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2909062909816541374/posts/default/1903649280342967022'/><link rel='alternate' type='text/html' href='http://signmotion.blogspot.com/2012/06/nosql-couchdb-iii.html' title='Чего не хватает в NoSQL-хранилищах (на примере CouchDB) - Часть III'/><author><name>Andrii</name><uri>http://www.blogger.com/profile/02715216472597824596</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjcrHHkyfsW8m8HmZZeyd2fhzwEl-shXbCxnYVY_mVq7uJpe5QET9SerP_bCPeO4YEBlXJT44IRPOcL7VtgFJsDqXwfppdES-fdokbXX0-11jdBQAyipvURKBH3N-Wh2VCye2U-W4nsp6zPgNSyi7g6gFgmmo34dH_oL_FTXf31U65BXQ/s220/Andrey-400x.png'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhoXkiU8W_6RFtDMka5wSv1dsnPJjuOfMmyWs2AW30aLXcLNWtJwS8PHYrcdk_1i9ytEFpoqJPZYW0UAZyUEk1ms6ycluWOK4_IbZCoRaEH4adSMQOrp_ao5-0fyoeRf5kdVfMW_QU9B6Ar/s72-c/nosql-bi-couchdb-bigdata-3.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2909062909816541374.post-4929045554076041214</id><published>2012-05-16T18:25:00.003+03:00</published><updated>2015-11-03T18:39:07.997+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="CouchDB"/><title type='text'>Чего не хватает в NoSQL-хранилищах (на примере CouchDB) - Часть II</title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: left; float: left; margin-bottom: 1em; margin-right: 1em; text-align: center;&quot;&gt;
&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj4lZUaxnqR48hkUxJ-gGA1kBEyRio3RgI34ZJ06ktNpsgah8aONxS04BQ9NPw9FE2Vy406a2XXiw9NOSXXyYBUWOaX5vk6Ve5Z6vecyZDZiXiGccrt5glTcBolXWhXdopFu-eDZz-U5AHD/s1600/nosql-bi-couchdb-bigdata-2.png&quot; /&gt;&lt;/div&gt;
Продолжение. Начало &amp;gt; &lt;a href=&quot;http://signmotion.blogspot.com/2012/05/nosql-couchdb.html&quot;&gt;&quot;Чего не хватает в NoSQL-хранилищах. Часть I&quot;&lt;/a&gt;.&lt;br /&gt;
&lt;ol&gt;
&lt;li value=&quot;6&quot;&gt;&lt;b&gt;Более тонкая авторизация&lt;/b&gt;. &lt;a href=&quot;http://www.automatthew.com/2008/01/planned-security-model-for-couchdb.html&quot;&gt;Заглянув в прошлое&lt;/a&gt;, можно увидеть: с момента официального выпуска &lt;a href=&quot;http://jacobian.org/writing/couchdb/&quot;&gt;1-й&lt;/a&gt; версии CouchDB, в вопросах защиты информации от постороннего взгляда проделана большая работа. Причина в том, что одним из пунктов идеологии этой свободно распространяемой системы системы было &lt;i&gt;сделать информацию общедоступной&lt;/i&gt;. Чудесная идея. Но войны требуют секретов. А современный рынок - это война и политика, здесь пока нет места для &lt;i&gt;помощи&lt;/i&gt;. И разработчики &lt;a href=&quot;http://opennet.ru/opennews/art.shtml?num=32735&quot;&gt;пошли&lt;/a&gt; &lt;strike&gt;рынку&lt;/strike&gt; реальности навстречу.&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Доступность ленты изменений в представлениях&lt;/b&gt;. Одна из уникальных особенностей CouchDB в том, что в неё можно сразу (сразу!) положить данные в любом (в любом!) виде и получать информацию в нужной нам форме тогда, когда (когда!) в этой информации возникла потребность. В этом нам помогают &lt;a href=&quot;http://ruseller.com/lessons.php?rub=28&amp;amp;id=1197&quot;&gt;представления CouchDB&lt;/a&gt;. Но хочется б&lt;i&gt;о&lt;/i&gt;льшего! И быстро трансформировать ленту изменений http://127.0.0.1:5984/database/_changes &lt;i&gt;своим&lt;/i&gt; представлением - одно из этих &quot;хочу&quot;.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Богатая поддержка reduce-функций&lt;/b&gt;. Google ввела в мир вычислений модель &quot;&lt;a href=&quot;http://express-js.ru/mongo-book/Glava-6-MapReduce.html&quot;&gt;Map/Reduce&lt;/a&gt;&quot;. CouchDB использует эту технологию... в &lt;a href=&quot;http://damienkatz.net/2008/02/incremental_map.html&quot;&gt;&lt;i&gt;накопительном&lt;/i&gt;&lt;/a&gt; виде: документ проходит обработку функциями map/reduce, достраивая &lt;a href=&quot;http://habrahabr.ru/post/114154/&quot;&gt;B-деревья&lt;/a&gt;, только при добавлении / изменении документа. Это быстро. Так быстро, что позволяет писать map/reduce запросы на JavaScript. С одной стороны, бывает необходимо, чтобы свёртка (reduce) проходила ещё быстрее (частично это решается использованием &lt;a href=&quot;http://wiki.apache.org/couchdb/Built-In_Reduce_Functions&quot;&gt;встроенных функций&lt;/a&gt;); с другой, &lt;strike&gt;не хочется&lt;/strike&gt; не эффективно создавать свёртки на JS для стандартных случаев (например, когда требуется получить список уникальных записей или сгруппировать элементы по ключу, суммируя их значения; тем более, что в &lt;a href=&quot;http://ru.wiki.mongodb.org/display/DOCS/Aggregation&quot;&gt;MongoDB это есть&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Частичное чтение документов.&lt;/b&gt; Можно запросто получать часть документов и сейчас, формируя нужный View. Но счастье это будет продолжаться ровно до тех пор, пока Вы не предложите CouchDB действительно много - по теперешним меркам, более 1 млн. - документов (записей). Тут вдруг оказывается, что 100 Гб на базу - это вовсе не &quot;немеряно места&quot;. Копаем глубже - и видим: созданные нами view-представления довольно прожорливы. Лучший (и, похоже, наиболее эффективный) способ умерить их аппетит - извлекать из хранилища &lt;i&gt;минимум&lt;/i&gt; информации, а приложением отправлять отдельный запрос при необходимости вытянуть нужные части документа. В не таком уж далёком прошлом, когда файлы &lt;i&gt;не рекомендовалось&lt;/i&gt; &lt;a href=&quot;http://rsdn.ru/forum/db/1257588.all.aspx&quot;&gt;хранить в SQL-базах&lt;/a&gt;, желание читать часть документа (записи) ни у кого не возникало: просто получали всю запись и были счастливы. CouchDB вполне может заменить привычную файловую систему. И разработчики &lt;a href=&quot;http://groups.google.com/group/couchapp/browse_thread/thread/366c1d5c7602f729/b8e0351dc0ef9d8a?pli=1&quot;&gt;рекомендуют&lt;/a&gt; использовать эту возможность. В результате, неожиданно, ага, можем получить хранилище, в котором документы весят по сотне мегабайт. К счастью, CouchDB не отправляет бинарные файлы вместе с документом. Но если необходимо обрабатывать содержимое файлов view-выборками, хранение содержимого в поле документа оказывается единственным выходом. И тогда может спасти только чтение нужных &lt;i&gt;сейчас&lt;/i&gt; полей, оставляя тяжёлые данные на сервере. &lt;/li&gt;
&lt;li&gt;&lt;b&gt;Расширение и рефакторинг протокола view-cервера.&lt;/b&gt; Для тех, кому JavaScript язык не родной, CouchDB предоставляет возможность создавать представления (view) практически на &lt;i&gt;любом &lt;/i&gt;известном сегодня языке программирования. Мне не приходилось создавать свой view-сервер (я люблю JavaScript). Наверное, в реализации протокола действительно не всё хорошо, раз это пожелание вошло в первую десятку. Тем не менее, сейчас &lt;i&gt;уже есть&lt;/i&gt; view-серверы для &lt;a href=&quot;http://wiki.apache.org/couchdb/View_server#Implementations&quot;&gt;многих языков&lt;/a&gt;. &lt;/li&gt;
&lt;/ol&gt;
&lt;br /&gt;
&lt;a href=&quot;http://signmotion.blogspot.com/2012/06/nosql-couchdb-iii.html&quot;&gt;Продолжение (чит. дальше) &amp;gt;&amp;gt;&lt;/a&gt;</content><link rel='replies' type='application/atom+xml' href='http://signmotion.blogspot.com/feeds/4929045554076041214/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2909062909816541374/4929045554076041214?isPopup=true' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2909062909816541374/posts/default/4929045554076041214'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2909062909816541374/posts/default/4929045554076041214'/><link rel='alternate' type='text/html' href='http://signmotion.blogspot.com/2012/05/nosql-couchdb-ii.html' title='Чего не хватает в NoSQL-хранилищах (на примере CouchDB) - Часть II'/><author><name>Andrii</name><uri>http://www.blogger.com/profile/02715216472597824596</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjcrHHkyfsW8m8HmZZeyd2fhzwEl-shXbCxnYVY_mVq7uJpe5QET9SerP_bCPeO4YEBlXJT44IRPOcL7VtgFJsDqXwfppdES-fdokbXX0-11jdBQAyipvURKBH3N-Wh2VCye2U-W4nsp6zPgNSyi7g6gFgmmo34dH_oL_FTXf31U65BXQ/s220/Andrey-400x.png'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj4lZUaxnqR48hkUxJ-gGA1kBEyRio3RgI34ZJ06ktNpsgah8aONxS04BQ9NPw9FE2Vy406a2XXiw9NOSXXyYBUWOaX5vk6Ve5Z6vecyZDZiXiGccrt5glTcBolXWhXdopFu-eDZz-U5AHD/s72-c/nosql-bi-couchdb-bigdata-2.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2909062909816541374.post-3273402589418735932</id><published>2012-05-10T19:02:00.000+03:00</published><updated>2015-11-03T18:38:47.774+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="CouchDB"/><title type='text'>Чего не хватает в NoSQL-хранилищах (на примере CouchDB) - Часть I</title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: left; float: left; margin-bottom: 1em; margin-right: 1em; text-align: center;&quot;&gt;
&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhGHfJ8pZQ0DsJNVjCQKf6zx0YtHCE55IOX-XejLxrW5YykhUEgIHNVcla-MkBe6XMxp0WQN4GxtrhNN1egGoehdx_-Zmrwu_bRm-ajUMc_Wtv2as4IEq-wCenIhGJjw2hzrZYpHm5GVSH4/s1600/nosql-bi-couchdb-bigdata-1.png&quot; /&gt;&lt;/div&gt;
На днях завершился опрос о плюшках, которых не хватает в NoSQL-хранилище &lt;a href=&quot;http://ru.wikipedia.org/wiki/CouchDB&quot;&gt;CouchDB&lt;/a&gt;. С этой базой я знаком уже года два, последний - активно. И, читая новости, вижу, что много вопросов по NoSQL могло быть не задано, не пытайся люди &lt;strike&gt;одеть рубашку, не сняв пальто&lt;/strike&gt;&lt;strike&gt;&lt;/strike&gt; применить свои знания SQL-парадигмы к тому, что к SQL отношения не имеет. Пример? Oracle у многих ассоциируется с SQL. Да, сам сервер, в отличии от сервиса, хорош. Но тот NoSQL что &lt;a href=&quot;http://blog.couchbase.com/couchbase-welcomes-oracle-to-nosql&quot;&gt;они сваяли&lt;/a&gt; выглядит хилым зародышем по сравнению с тем, что уже &lt;i&gt;давно есть в бесплатных системах&lt;/i&gt;. Новое лучше воспринимать с пустой головой.&lt;br /&gt;
&lt;br /&gt;
Оказалось, &lt;b&gt;больше всего &lt;strike&gt;жгут&lt;/strike&gt; ждут&lt;/b&gt; (&lt;i&gt;прокомментирую некоторые пункты, опираясь на собственный опыт работы с CouchDB&lt;/i&gt;):&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;&lt;b&gt;Мощный язык запросов&lt;/b&gt;. Наверное, ожидают что-то типа &lt;a href=&quot;http://ru.wikipedia.org/wiki/SQL&quot;&gt;SQL&lt;/a&gt;, но, если задуматься, так ли горячо он нужен для &lt;i&gt;прикладных &lt;/i&gt;задач? А ведь на решение таких задач и нацелены NoSQL-решения. Новый язык - значит, больше времени на изучение, более дорогая поддержка готового продукта (много в мире окажется специалистов по этому языку?), выше &quot;порог входа&quot;... Японский мобильный оператор NTT DoCoMo (на &lt;a href=&quot;http://www.nttdocomo.com/about/operating/index.html&quot;&gt;март 2012 г.&lt;/a&gt; почти &lt;b&gt;60 млн.&lt;/b&gt; абонентов) почему-то &lt;a href=&quot;http://blog.couchbase.com/tag/couchbase-and-docomo&quot;&gt;выбрал CouchDB&lt;/a&gt; не заморачиваясь вопросом об эскьюэль-подобном языке.&lt;br /&gt;&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Ждут документацию&lt;/b&gt;. Что странно, т.к. информации в Интернете и в &lt;a href=&quot;http://couchdb.apache.org/#mailing-list&quot;&gt;списках рассылки CouchDB&lt;/a&gt; - крайне много. И разработчики - грамотные люди - ждать ответа не заставляют.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Цепочки map/reduce.&lt;/b&gt; Да, получить &quot;в коробке&quot; такую функциональность было бы неплохо. С другой стороны, как отдельный &quot;плагин&quot;, она давно &lt;a href=&quot;http://savdalion.blogspot.com/2011/10/couchdb-view-view.html&quot;&gt;есть&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Частичное обновление документов&lt;/b&gt;. Небольшой экскурс. CouchDB при обновлении делает копию документа (близкая аналогия документа в SQL - запись). Документ копируется целиком. Это быстро. Но бывает накладно; особенно, когда документы большие и обновляются часто. В общем-то, всегда можно спроектировать хранилище так, что о &lt;i&gt;частичном обновлении&lt;/i&gt; вспоминать не будете. Но проектирование = время. А чем мне нравится CouchDB, это возможностью &lt;i&gt;за две-три недели&lt;/i&gt; создать продукт, который &quot;уже можно дать пощупать&quot;. Признаюсь, после Lisp, Java, [T-]SQL, PHP, JavaScript и С++ скорость NoSQL-разработки меня очень впечатлила.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;API для управления фоновыми процессами&lt;/b&gt;. У NoSQL-баз есть интересная особенность: они выдают результат &lt;i&gt;мгновенно&lt;/i&gt;... если им дали время подготовить его. Иначе, к примеру, при миллионе записей, временем на кофе / почитать / поспать (всё это вместе - не редкое исключение) Вы себя обеспечили. Бывает полезно отключить тяжёлые процессы, ускорив тем самым &quot;нужные сейчас вычисления&quot;. Например, отменить репликацию или сжатие базы, т.к. вдруг узнали что &quot;много клиентов, а компьютеры сегодня очень тормозят&quot;... Нужное требование. Но вверху списка? Нет, далеко не для всех.&lt;/li&gt;
&lt;/ol&gt;
Здесь ещё более &lt;a href=&quot;http://www.allourideas.org/couchdb2012/results?more=true&quot;&gt;20-ти&lt;/a&gt; пунктов. Бооольшой список...&lt;br /&gt;
&lt;br /&gt;
Скриншот (см. ниже) и &lt;a href=&quot;http://signmotion.blogspot.com/2012/05/nosql-couchdb-ii.html&quot;&gt;продолжение (чит. дальше) &amp;gt;&amp;gt;&lt;/a&gt; &lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi1EblspaV8J83RkjpKYY8vSIFs85RaZA2FHRfI7UrJBxACOz-rdZEQrCc791sShQrtdKdLwPS939AXHWc9Pjkg_NZKHN-ot64H47DsAIEDNG_7R3k-sD5Boru5GsvkvuxoU4s2oy30aGjz/s1600/imortant-feature-couchdb-implement.png&quot; /&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://signmotion.blogspot.com/feeds/3273402589418735932/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2909062909816541374/3273402589418735932?isPopup=true' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2909062909816541374/posts/default/3273402589418735932'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2909062909816541374/posts/default/3273402589418735932'/><link rel='alternate' type='text/html' href='http://signmotion.blogspot.com/2012/05/nosql-couchdb.html' title='Чего не хватает в NoSQL-хранилищах (на примере CouchDB) - Часть I'/><author><name>Andrii</name><uri>http://www.blogger.com/profile/02715216472597824596</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjcrHHkyfsW8m8HmZZeyd2fhzwEl-shXbCxnYVY_mVq7uJpe5QET9SerP_bCPeO4YEBlXJT44IRPOcL7VtgFJsDqXwfppdES-fdokbXX0-11jdBQAyipvURKBH3N-Wh2VCye2U-W4nsp6zPgNSyi7g6gFgmmo34dH_oL_FTXf31U65BXQ/s220/Andrey-400x.png'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhGHfJ8pZQ0DsJNVjCQKf6zx0YtHCE55IOX-XejLxrW5YykhUEgIHNVcla-MkBe6XMxp0WQN4GxtrhNN1egGoehdx_-Zmrwu_bRm-ajUMc_Wtv2as4IEq-wCenIhGJjw2hzrZYpHm5GVSH4/s72-c/nosql-bi-couchdb-bigdata-1.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2909062909816541374.post-7728436915560584740</id><published>2012-02-29T14:11:00.001+02:00</published><updated>2012-07-24T16:21:07.633+03:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="C++"/><title type='text'>Потоки C++: boost::thread error LNK2001 boost::exception_ptr</title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: left; float: left; margin-bottom: 1em; margin-right: 1em; text-align: center;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjyijDMm6zMVb5sV5sMyiMAN7dLQaLe8Kqieyg4umb-DmpNXEcyOxUzGr7xh_EI22zsBtsDlNWPmWuRHGwwQl_7PD8oQfOiD-xMpO8qECxpetyMhfm448XLwIr9RamaJLs8pSXwf40FcvXM/s1600/bug-boost-c%252B%252B.png&quot; /&gt;&lt;/div&gt;Непонятный заголовок, т.к. речь пойдёт о такой же &lt;strike&gt;непонятной&lt;/strike&gt; ошибке С++, возникающей при работе с потоками (нитями) boost::thread. &lt;br /&gt;
&lt;br /&gt;
Компилятор MS&amp;nbsp;Visual&amp;nbsp;C++&amp;nbsp;2010, &lt;a href=&quot;http://boost.org/&quot;&gt;Boost&amp;nbsp;1.49&lt;/a&gt;. &lt;br /&gt;
&lt;br /&gt;
В Интернете встречаются обсуждения, но решения проблемы я не нашёл. Как выглядит, пример: &lt;br /&gt;
&lt;pre&gt;&lt;code class=&quot;C++&quot; style=&quot;clear: both;&quot;&gt;1&amp;gt;World.obj : error LNK2001: неразрешенный внешний символ
    public: static class boost::exception_ptr const \
        boost::exception_detail\
        ::exception_ptr_static_exception_object&lt;struct \=&quot;&quot; boost::exception_detail::bad_alloc_=&quot;&quot;&gt;::e \
        (?e@?$exception_ptr_static_exception_object\
         @Ubad_alloc_@exception_detail@boost\
         @@@exception_detail@boost@@2Vexception_ptr@3@B)
&lt;/struct&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
Как исправить.&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
&lt;b&gt;Вариант I&lt;/b&gt;. Не использовать предварительно откомпилированный заголовок. Это удобное решение для маленького проекта. Когда проект большой, заметны последствия: время компиляции значительно увеличивается. &lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Вариант II&lt;/b&gt;. Переместить &lt;br /&gt;
&lt;pre&gt;&lt;code class=&quot;C++&quot;&gt;#include &amp;lt;boost/thread.hpp&amp;gt;&lt;/code&gt;&lt;/pre&gt;из файла предварительно откомпилированного заголовка в файлы, где используются потоки. Больше движений, но без последствий для проектов любого размера.</content><link rel='replies' type='application/atom+xml' href='http://signmotion.blogspot.com/feeds/7728436915560584740/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2909062909816541374/7728436915560584740?isPopup=true' title='Комментарии: 2'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2909062909816541374/posts/default/7728436915560584740'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2909062909816541374/posts/default/7728436915560584740'/><link rel='alternate' type='text/html' href='http://signmotion.blogspot.com/2012/02/c-boostthread-error-lnk2001.html' title='Потоки C++: boost::thread error LNK2001 boost::exception_ptr'/><author><name>Andrii</name><uri>http://www.blogger.com/profile/02715216472597824596</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjcrHHkyfsW8m8HmZZeyd2fhzwEl-shXbCxnYVY_mVq7uJpe5QET9SerP_bCPeO4YEBlXJT44IRPOcL7VtgFJsDqXwfppdES-fdokbXX0-11jdBQAyipvURKBH3N-Wh2VCye2U-W4nsp6zPgNSyi7g6gFgmmo34dH_oL_FTXf31U65BXQ/s220/Andrey-400x.png'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjyijDMm6zMVb5sV5sMyiMAN7dLQaLe8Kqieyg4umb-DmpNXEcyOxUzGr7xh_EI22zsBtsDlNWPmWuRHGwwQl_7PD8oQfOiD-xMpO8qECxpetyMhfm448XLwIr9RamaJLs8pSXwf40FcvXM/s72-c/bug-boost-c%252B%252B.png" height="72" width="72"/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2909062909816541374.post-8221019078020044026</id><published>2011-12-16T11:01:00.001+02:00</published><updated>2015-11-03T18:37:14.038+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="C++"/><title type='text'>Число. Обрезать до байта? Быстро? Легко!</title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: left; float: left; margin-bottom: 1em; margin-right: 1em; text-align: center;&quot;&gt;
&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgEcTgmHkZuVnzbu6i0Hvwia1QG9iBeHujQ0AZbExO_UClFHi-gobQrFrKei3FTCnIaLcebv_uxtNqTFad90e15ohQmIAhYHdeFmE3zUZdnvTDyN_qFqsiCHrfSk-6LLwV_qURBdmgjl0-Y/s1600/clamp-int-byte-char.png&quot; /&gt;&lt;/div&gt;
Когда выполняются вычисления на графических картах (GPU), создаются текстуры, или, например, данные готовятся к серилизации, бывает, нужно привести поток данных к жёстко фиксированному диапазону. Хорошо, если мы активно используем &lt;a href=&quot;http://www.khronos.org/opencl/&quot;&gt;OpenCL&lt;/a&gt;: тогда есть готовая &lt;a href=&quot;http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/&quot;&gt;инструкция&lt;/a&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code class=&quot;opencl&quot;&gt;gentype clamp(
    gentype x,
    gentype minval,
    gentype maxval)&lt;/code&gt;&lt;/pre&gt;
Но никто в здравом уме не будет городить тяжеловесный OpenCL, чтобы привести int к unsigned char.&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
Обычно, для приведения числа к [0; 255] на CPU я пользовался таким кодом (С++): &lt;br /&gt;
&lt;pre&gt;&lt;code class=&quot;C++&quot;&gt;char byteN = (intN &amp;gt; 255) ? 255 : (intN &amp;lt; 0) ? 0 : intN;
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
&lt;a href=&quot;http://codereview.stackexchange.com/questions/6502/fastest-way-to-clamp-an-integer-to-the-range-0-255?newsletter=1&amp;amp;nlcode=29222%7c1fd9&quot;&gt;Оказывается&lt;/a&gt;, есть  более быстрый способ. Когда-нибудь компиляторы C++ научатся лучше понимать, чего от них хотят. Ну а пока такой вот код для приведения целого числа к беззнаковому байту - самый-самый:&lt;br /&gt;
&lt;pre&gt;&lt;code class=&quot;C++&quot;&gt;unsigned char clamp( int n ) {
    int a = 255;
    a -= n;
    a &amp;gt;&amp;gt;= 31;
    a |= n;
    n &amp;gt;&amp;gt;= 31;
    n = ~n;
    n &amp;amp;= a;
    return n;
}&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
Мне этот код не нравится. Но если он понравился Вам, наверняка, понравится и содержимое этой страницы &amp;gt;&lt;a href=&quot;http://graphics.stanford.edu/%7Eseander/bithacks.html&quot;&gt;http://graphics.stanford.edu/~seander/bithacks.html&lt;/a&gt;&lt;br /&gt;
Крайне быстро. Крайне непонятно. Крайне эффективно. C++) &lt;br /&gt;
&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://signmotion.blogspot.com/feeds/8221019078020044026/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2909062909816541374/8221019078020044026?isPopup=true' title='Комментарии: 1'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2909062909816541374/posts/default/8221019078020044026'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2909062909816541374/posts/default/8221019078020044026'/><link rel='alternate' type='text/html' href='http://signmotion.blogspot.com/2011/12/blog-post.html' title='Число. Обрезать до байта? Быстро? Легко!'/><author><name>Andrii</name><uri>http://www.blogger.com/profile/02715216472597824596</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjcrHHkyfsW8m8HmZZeyd2fhzwEl-shXbCxnYVY_mVq7uJpe5QET9SerP_bCPeO4YEBlXJT44IRPOcL7VtgFJsDqXwfppdES-fdokbXX0-11jdBQAyipvURKBH3N-Wh2VCye2U-W4nsp6zPgNSyi7g6gFgmmo34dH_oL_FTXf31U65BXQ/s220/Andrey-400x.png'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgEcTgmHkZuVnzbu6i0Hvwia1QG9iBeHujQ0AZbExO_UClFHi-gobQrFrKei3FTCnIaLcebv_uxtNqTFad90e15ohQmIAhYHdeFmE3zUZdnvTDyN_qFqsiCHrfSk-6LLwV_qURBdmgjl0-Y/s72-c/clamp-int-byte-char.png" height="72" width="72"/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2909062909816541374.post-5687762901010992818</id><published>2011-12-03T01:46:00.001+02:00</published><updated>2011-12-12T09:06:10.850+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="C++"/><title type='text'>Ленивое сравнение для boost::any()</title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: left; float: left; margin-bottom: 1em; margin-right: 1em; text-align: center;&quot;&gt;
&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhAHnl9MB1PU3GLkAhENx08QOFYqqGgeEbOqex6By0gxPdS3el_YtmtyHEAoBMWnYD-KrpJJw8CBsiZEKllyH1zD0vpxLA-tEBZLxA4kicgocl3wBcfi7hV0MMTWYTvJDXxIqhqWHneqObM/s1600/boost-any-equals.png&quot; /&gt;&lt;/div&gt;
Понадобилось мне быстро распарсить много данных из XML-файла. Возможность хранить всё, предлагаемая &lt;a href=&quot;http://boost.org/doc/libs/1_48_0/doc/html/any.html&quot;&gt;boost::any&lt;/a&gt;, как бы предполагает возможность это &quot;всё&quot; сравнивать... Ан нет! Выяснилось, что для &lt;b&gt;boost::any&lt;/b&gt; (в который собирались xml-данные) готового сравнения нет. В общем-то, если &lt;a href=&quot;http://lists.boost.org/Archives/boost/2006/04/103272.php&quot;&gt;задуматься&lt;/a&gt;, это логично. Но я так привык работать с нестрого типизированными языками, что просто не мог смириться. C++ - злой язык :) Время на написание довольно скучного кода было потрачено. И если Вам нужен &lt;b&gt;equals() для boost::any()&lt;/b&gt; - код ниже.

&lt;br /&gt;
&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
Метод equals( boost::any, boost::any ) возвращает пару булевых значений:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;(1) проверка на равенство типов&lt;/li&gt;
&lt;li&gt;(2) проверка собственно самих значений &lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
Сравнение я назвал &quot;ленивым&quot;, т.к. если простые типы оказались не равными и &lt;i&gt;хотя бы одно&lt;/i&gt; из значений является строкой, делается попытка распознать в строках числа и сравнить их.&lt;br /&gt;
&lt;br /&gt;
Типами метод чрезмерно не нагружал, т.к. каждая проверка - это процессорное время. Вы можете запросто добавить в код свои типы и/или исключить имеющиеся. Ведь код должен эффективно решать поставленную задачу и (в идеале) быть лёгким для понимания. Остальное - от лукавого!&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;&lt;code class=&quot;c++&quot;&gt;/**
* Сравнивает два значения boost::any.
*
* (!) Может возвращать ( false, true ), т.к. числа разных типов
* сравниваются как числа.
*
* @param precision Точность для сравнения значений с плавающей точкой.
*/
inline std::pair&amp;lt;
    // типы совпадают?
    bool,
    // содержимое совпадает?
    bool
&amp;gt; lazyEquals(
    const boost::any&amp;amp; a,
    const boost::any&amp;amp; b,
    double precision = 1e-8
) {
    using namespace boost;

    // Быстрая оценка на равенство
    const type_info&amp;amp; at = a.type();
    const type_info&amp;amp; bt = b.type();
    std::pair&amp;lt; bool, bool &amp;gt;  r = std::make_pair(
        (at == bt),
        false
    );
    
    // double
    if (at == typeid( double )) {
        const auto ca = any_cast&amp;lt; double &amp;gt;( a );
        double cb = numeric_limits&amp;lt; double &amp;gt;::infinity();
        if (bt == typeid( double )) {
            cb = any_cast&amp;lt; double &amp;gt;( b );
        } else if (bt == typeid( float )) {
            cb = (double)any_cast&amp;lt; float &amp;gt;( b );
        } else if (bt == typeid( int )) {
            cb = (double)any_cast&amp;lt; int &amp;gt;( b );
        } else if (bt == typeid( size_t )) {
            cb = (double)any_cast&amp;lt; size_t &amp;gt;( b );
        } else if (bt == typeid( string )) {
            cb = numberCast( any_cast&amp;lt; string &amp;gt;( b ) );
            // Получим infinity(), если не число
        }
        if (cb != numeric_limits&amp;lt; double &amp;gt;::infinity()) {
            r.second = (precision &amp;gt; std::abs( ca - cb ));
        }

    // float
    } else if (at == typeid( float )) {
        const auto ca = any_cast&amp;lt; float &amp;gt;( a );
        float cb = numeric_limits&amp;lt; float &amp;gt;::infinity();
        if (bt == typeid( double )) {
            cb = (float)any_cast&amp;lt; double &amp;gt;( b );
        } else if (bt == typeid( float )) {
            cb = any_cast&amp;lt; float &amp;gt;( b );
        } else if (bt == typeid( int )) {
            cb = (float)any_cast&amp;lt; int &amp;gt;( b );
        } else if (bt == typeid( size_t )) {
            cb = (float)any_cast&amp;lt; size_t &amp;gt;( b );
        } else if (bt == typeid( string )) {
            cb = (float)numberCast( any_cast&amp;lt; string &amp;gt;( b ) );
            // Получим infinity(), если не число
        }
        if (cb != numeric_limits&amp;lt; float &amp;gt;::infinity()) {
            r.second = (precision &amp;gt; std::abs( ca - cb ));
        }

    // int
    } else if (at == typeid( int )) {
        const auto ca = any_cast&amp;lt; int &amp;gt;( a );
        if (bt == typeid( double )) {
            r.second = (ca == (int)any_cast&amp;lt; double &amp;gt;( b ));
        } else if (bt == typeid( float )) {
            r.second = (ca == any_cast&amp;lt; float &amp;gt;( b ));
        } else if (bt == typeid( int )) {
            r.second = (ca == any_cast&amp;lt; int &amp;gt;( b ));
        } else if (bt == typeid( size_t )) {
            r.second = (ca == (int)any_cast&amp;lt; size_t &amp;gt;( b ));
        } else if (bt == typeid( string )) {
            const double temp = numberCast( any_cast&amp;lt; string &amp;gt;( b ) );
            // Получим infinity(), если не число
            if (temp != numeric_limits&amp;lt; double &amp;gt;::infinity()) {
                r.second = (ca == (int)temp);
            }
        }

    // size_t
    } else if (at == typeid( size_t )) {
        const auto ca = any_cast&amp;lt; size_t &amp;gt;( a );
        if (bt == typeid( double )) {
            r.second = (ca == (size_t)any_cast&amp;lt; double &amp;gt;( b ));
        } else if (bt == typeid( float )) {
            r.second = (ca == (size_t)any_cast&amp;lt; float &amp;gt;( b ));
        } else if (bt == typeid( int )) {
            r.second = (ca == (size_t)any_cast&amp;lt; int &amp;gt;( b ));
        } else if (bt == typeid( size_t )) {
            r.second = (ca == any_cast&amp;lt; size_t &amp;gt;( b ));
        } else if (bt == typeid( string )) {
            const double temp = numberCast( any_cast&amp;lt; string &amp;gt;( b ) );
            // Получим infinity(), если не число
            if (temp != numeric_limits&amp;lt; double &amp;gt;::infinity()) {
                r.second = (ca == (size_t)temp);
            }
        }

    // string
    } else if (at == typeid( string )) {
        const string ca = any_cast&amp;lt; string &amp;gt;( a );
        if (bt == typeid( string )) {
            r.second = (ca == any_cast&amp;lt; string &amp;gt;( b ));
        }
        // Может, число представлено строкой? Строки переведём
        // в числа и сравним числа согласно их типу.
        const double nca = numberCast( ca );
        if (nca != numeric_limits&amp;lt; double &amp;gt;::infinity()) {
            if (bt == typeid( double )) {
                const auto ncb = any_cast&amp;lt; double &amp;gt;( b );
                r.second = (precision &amp;gt; std::abs( nca - ncb ));
            } else if (bt == typeid( float )) {
                const auto ncb = any_cast&amp;lt; float &amp;gt;( b );
                r.second = (precision &amp;gt; std::abs( (float)nca - ncb ));
            } else if (bt == typeid( int )) {
                const auto ncb = any_cast&amp;lt; int &amp;gt;( b );
                r.second = ((int)nca == ncb);
            } else if (bt == typeid( size_t )) {
                const auto ncb = any_cast&amp;lt; size_t &amp;gt;( b );
                r.second = ((size_t)nca == ncb);
            }
            // string посмотрели выше
        }

    } // if-else ...

    return r;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
В методе используется вот такая функция, которая &lt;strike&gt;кастует&lt;/strike&gt; преобразует строку в число: &lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;&lt;code class=&quot;c++&quot;&gt;/**
* @return Распознанное число или numeric_limits&amp;lt; double &amp;gt;::infinity().
*/
inline double numberCast( const string&amp;amp; s ) {
    try {
        const double number = boost::lexical_cast&amp;lt; double &amp;gt;( s );
        return number;
    }
    catch ( boost::bad_lexical_cast&amp;amp; ) {
        return numeric_limits&amp;lt; double &amp;gt;::infinity();
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
И, конечно же, тесты! Без них любой код смотрится подозрительно. Используем &lt;a href=&quot;http://code.google.com/p/googletest&quot;&gt;googletest&lt;/a&gt;. Надо говорить, что все t. - зелёные? &lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;&lt;code class=&quot;c++&quot;&gt;/**
* Фикстура.
*/
class DTest : public ::testing::Test {
  protected:
    inline DTest() {
    }

    virtual inline ~DTest() {
    }

    virtual inline void SetUp() {
    }

    virtual void TearDown() {
    }
};
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
Одинаковые типы данных
&lt;br /&gt;
&lt;pre&gt;&lt;code class=&quot;c++&quot;&gt;TEST_F( DTest, IntEqualsInt_LazyEquals ) {
    const auto a = boost::any( (int)100 );
    const auto b = boost::any( (int)100 );
    const auto r = d::lazyEquals( a, b );
    EXPECT_TRUE( r.first );
    EXPECT_TRUE( r.second );
}


TEST_F( DTest, IntNotEqualsInt_LazyEquals ) {
    const auto a = boost::any( (int)100 );
    const auto b = boost::any( (int)200 );
    const auto r = d::lazyEquals( a, b );
    EXPECT_TRUE( r.first );
    EXPECT_FALSE( r.second );
}


TEST_F( DTest, SizeTEqualsSizeT_LazyEquals ) {
    const auto a = boost::any( (size_t)100 );
    const auto b = boost::any( (size_t)100 );
    const auto r = d::lazyEquals( a, b );
    EXPECT_TRUE( r.first );
    EXPECT_TRUE( r.second );
}


TEST_F( DTest, SizeTNotEqualsSizeT_LazyEquals ) {
    const auto a = boost::any( (size_t)100 );
    const auto b = boost::any( (size_t)200 );
    const auto r = d::lazyEquals( a, b );
    EXPECT_TRUE( r.first );
    EXPECT_FALSE( r.second );
}


TEST_F( DTest, FloatEqualsFloat_LazyEquals ) {
    const auto a = boost::any( (float)100 );
    const auto b = boost::any( (float)100 );
    const auto r = d::lazyEquals( a, b );
    EXPECT_TRUE( r.first );
    EXPECT_TRUE( r.second );
}


TEST_F( DTest, FloatNotEqualsFloat_LazyEquals ) {
    const auto a = boost::any( (float)100 );
    const auto b = boost::any( (float)200 );
    const auto r = d::lazyEquals( a, b );
    EXPECT_TRUE( r.first );
    EXPECT_FALSE( r.second );
}


TEST_F( DTest, DoubleEqualsDouble_LazyEquals ) {
    const auto a = boost::any( (double)100 );
    const auto b = boost::any( (double)100 );
    const auto r = d::lazyEquals( a, b );
    EXPECT_TRUE( r.first );
    EXPECT_TRUE( r.second );
}


TEST_F( DTest, DoubleNotEqualsDouble_LazyEquals ) {
    const auto a = boost::any( (double)100 );
    const auto b = boost::any( (double)200 );
    const auto r = d::lazyEquals( a, b );
    EXPECT_TRUE( r.first );
    EXPECT_FALSE( r.second );
}


TEST_F( DTest, StringLatinEqualsStringLatin_LazyEquals ) {
    const auto a = boost::any( (string)&quot;abcd&quot; );
    const auto b = boost::any( (string)&quot;abcd&quot; );
    const auto r = d::lazyEquals( a, b );
    EXPECT_TRUE( r.first );
    EXPECT_TRUE( r.second );
}


TEST_F( DTest, StringLatinNotEqualsStringLatin_LazyEquals ) {
    const auto a = boost::any( (string)&quot;abcd&quot; );
    const auto b = boost::any( (string)&quot;abcdefgh&quot; );
    const auto r = d::lazyEquals( a, b );
    EXPECT_TRUE( r.first );
    EXPECT_FALSE( r.second );
}


TEST_F( DTest, StringUnicodeEqualsStringUnicode_LazyEquals ) {
    const auto a = boost::any( (string)&quot;Юникод&quot; );
    const auto b = boost::any( (string)&quot;Юникод&quot; );
    const auto r = d::lazyEquals( a, b );
    EXPECT_TRUE( r.first );
    EXPECT_TRUE( r.second );
}


TEST_F( DTest, StringUnicodeNotEqualsStringUnicode_LazyEquals ) {
    const auto a = boost::any( (string)&quot;Юникод&quot; );
    const auto b = boost::any( (string)&quot;Юникод тоже&quot; );
    const auto r = d::lazyEquals( a, b );
    EXPECT_TRUE( r.first );
    EXPECT_FALSE( r.second );
}
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
Разные типы данных
&lt;br /&gt;
&lt;pre&gt;&lt;code class=&quot;c++&quot;&gt;TEST_F( DTest, IntEqualsSizeT_LazyEquals ) {
    auto a = boost::any( (int)100 );
    auto b = boost::any( (size_t)100 );
    auto r = d::lazyEquals( a, b );
    EXPECT_FALSE( r.first );
    EXPECT_TRUE( r.second );

    a = boost::any( (size_t)100 );
    b = boost::any( (int)100 );
    r = d::lazyEquals( a, b );
    EXPECT_FALSE( r.first );
    EXPECT_TRUE( r.second );
}


TEST_F( DTest, IntNotEqualsSizeT_LazyEquals ) {
    auto a = boost::any( (int)100 );
    auto b = boost::any( (size_t)200 );
    auto r = d::lazyEquals( a, b );
    EXPECT_FALSE( r.first );
    EXPECT_FALSE( r.second );

    a = boost::any( (size_t)100 );
    b = boost::any( (int)200 );
    r = d::lazyEquals( a, b );
    EXPECT_FALSE( r.first );
    EXPECT_FALSE( r.second );
}


TEST_F( DTest, IntEqualsFloat_LazyEquals ) {
    auto a = boost::any( (int)100 );
    auto b = boost::any( (float)100 );
    auto r = d::lazyEquals( a, b );
    EXPECT_FALSE( r.first );
    EXPECT_TRUE( r.second );

    a = boost::any( (float)100 );
    b = boost::any( (int)100 );
    r = d::lazyEquals( a, b );
    EXPECT_FALSE( r.first );
    EXPECT_TRUE( r.second );
}


TEST_F( DTest, IntNotEqualsFloat_LazyEquals ) {
    auto a = boost::any( (int)100 );
    auto b = boost::any( (float)200 );
    auto r = d::lazyEquals( a, b );
    EXPECT_FALSE( r.first );
    EXPECT_FALSE( r.second );

    a = boost::any( (float)100 );
    b = boost::any( (int)200 );
    r = d::lazyEquals( a, b );
    EXPECT_FALSE( r.first );
    EXPECT_FALSE( r.second );
}


TEST_F( DTest, IntEqualsDouble_LazyEquals ) {
    auto a = boost::any( (int)100 );
    auto b = boost::any( (double)100 );
    auto r = d::lazyEquals( a, b );
    EXPECT_FALSE( r.first );
    EXPECT_TRUE( r.second );

    a = boost::any( (double)100 );
    b = boost::any( (int)100 );
    r = d::lazyEquals( a, b );
    EXPECT_FALSE( r.first );
    EXPECT_TRUE( r.second );
}


TEST_F( DTest, IntNotEqualsDouble_LazyEquals ) {
    auto a = boost::any( (int)100 );
    auto b = boost::any( (double)200 );
    auto r = d::lazyEquals( a, b );
    EXPECT_FALSE( r.first );
    EXPECT_FALSE( r.second );

    a = boost::any( (double)100 );
    b = boost::any( (int)200 );
    r = d::lazyEquals( a, b );
    EXPECT_FALSE( r.first );
    EXPECT_FALSE( r.second );
}
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
Строки - Равенство
&lt;br /&gt;
&lt;pre&gt;&lt;code class=&quot;c++&quot;&gt;TEST_F( DTest, NumberEqualsString_LazyEquals ) {
    // int
    auto a = boost::any( (int)100 );
    auto b = boost::any( (string)&quot;100&quot; );
    auto r = d::lazyEquals( a, b );
    EXPECT_FALSE( r.first );
    EXPECT_TRUE( r.second );

    a = boost::any( (string)&quot;100&quot; );
    b = boost::any( (int)100 );
    r = d::lazyEquals( a, b );
    EXPECT_FALSE( r.first );
    EXPECT_TRUE( r.second );

    a = boost::any( (int)100 );
    b = boost::any( (string)&quot;100.0&quot; );
    r = d::lazyEquals( a, b );
    EXPECT_FALSE( r.first );
    EXPECT_TRUE( r.second );

    a = boost::any( (string)&quot;100.0&quot; );
    b = boost::any( (int)100 );
    r = d::lazyEquals( a, b );
    EXPECT_FALSE( r.first );
    EXPECT_TRUE( r.second );

    // size_t
    a = boost::any( (size_t)100 );
    b = boost::any( (string)&quot;100&quot; );
    r = d::lazyEquals( a, b );
    EXPECT_FALSE( r.first );
    EXPECT_TRUE( r.second );

    a = boost::any( (string)&quot;100&quot; );
    b = boost::any( (size_t)100 );
    r = d::lazyEquals( a, b );
    EXPECT_FALSE( r.first );
    EXPECT_TRUE( r.second );

    a = boost::any( (size_t)100 );
    b = boost::any( (string)&quot;100.0&quot; );
    r = d::lazyEquals( a, b );
    EXPECT_FALSE( r.first );
    EXPECT_TRUE( r.second );

    a = boost::any( (string)&quot;100.0&quot; );
    b = boost::any( (size_t)100 );
    r = d::lazyEquals( a, b );
    EXPECT_FALSE( r.first );
    EXPECT_TRUE( r.second );

    a = boost::any( (size_t)100 );
    b = boost::any( (string)&quot;100.1&quot; );
    r = d::lazyEquals( a, b );
    EXPECT_FALSE( r.first );
    EXPECT_TRUE( r.second );

    a = boost::any( (string)&quot;100.1&quot; );
    b = boost::any( (size_t)100 );
    r = d::lazyEquals( a, b );
    EXPECT_FALSE( r.first );
    EXPECT_TRUE( r.second );

    // float
    a = boost::any( (float)100 );
    b = boost::any( (string)&quot;100&quot; );
    r = d::lazyEquals( a, b );
    EXPECT_FALSE( r.first );
    EXPECT_TRUE( r.second );

    a = boost::any( (string)&quot;100&quot; );
    b = boost::any( (float)100 );
    r = d::lazyEquals( a, b );
    EXPECT_FALSE( r.first );
    EXPECT_TRUE( r.second );

    a = boost::any( (float)100 );
    b = boost::any( (string)&quot;100.0&quot; );
    r = d::lazyEquals( a, b );
    EXPECT_FALSE( r.first );
    EXPECT_TRUE( r.second );

    a = boost::any( (string)&quot;100.0&quot; );
    b = boost::any( (float)100 );
    r = d::lazyEquals( a, b );
    EXPECT_FALSE( r.first );
    EXPECT_TRUE( r.second );

    a = boost::any( (float)100.1 );
    b = boost::any( (string)&quot;100.1&quot; );
    r = d::lazyEquals( a, b );
    EXPECT_FALSE( r.first );
    EXPECT_TRUE( r.second );

    a = boost::any( (string)&quot;100.1&quot; );
    b = boost::any( (float)100.1 );
    r = d::lazyEquals( a, b );
    EXPECT_FALSE( r.first );
    EXPECT_TRUE( r.second );

    // double
    a = boost::any( (double)100 );
    b = boost::any( (string)&quot;100&quot; );
    r = d::lazyEquals( a, b );
    EXPECT_FALSE( r.first );
    EXPECT_TRUE( r.second );

    a = boost::any( (string)&quot;100&quot; );
    b = boost::any( (double)100 );
    r = d::lazyEquals( a, b );
    EXPECT_FALSE( r.first );
    EXPECT_TRUE( r.second );

    a = boost::any( (double)100 );
    b = boost::any( (string)&quot;100.0&quot; );
    r = d::lazyEquals( a, b );
    EXPECT_FALSE( r.first );
    EXPECT_TRUE( r.second );

    a = boost::any( (string)&quot;100.0&quot; );
    b = boost::any( (double)100 );
    r = d::lazyEquals( a, b );
    EXPECT_FALSE( r.first );
    EXPECT_TRUE( r.second );

    a = boost::any( (double)100.1 );
    b = boost::any( (string)&quot;100.1&quot; );
    r = d::lazyEquals( a, b );
    EXPECT_FALSE( r.first );
    EXPECT_TRUE( r.second );

    a = boost::any( (string)&quot;100.1&quot; );
    b = boost::any( (double)100.1 );
    r = d::lazyEquals( a, b );
    EXPECT_FALSE( r.first );
    EXPECT_TRUE( r.second );

}
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
Строки - Не равенство
&lt;br /&gt;
&lt;pre&gt;&lt;code class=&quot;c++&quot;&gt;TEST_F( DTest, NumberNotEqualsString2_LazyEquals ) {
    // int
    auto a = boost::any( (int)100 );
    auto b = boost::any( (string)&quot;200&quot; );
    auto r = d::lazyEquals( a, b );
    EXPECT_FALSE( r.first );
    EXPECT_FALSE( r.second );

    a = boost::any( (string)&quot;200&quot; );
    b = boost::any( (int)100 );
    r = d::lazyEquals( a, b );
    EXPECT_FALSE( r.first );
    EXPECT_FALSE( r.second );

    a = boost::any( (int)100 );
    b = boost::any( (string)&quot;200.0&quot; );
    r = d::lazyEquals( a, b );
    EXPECT_FALSE( r.first );
    EXPECT_FALSE( r.second );

    a = boost::any( (string)&quot;200.0&quot; );
    b = boost::any( (int)100 );
    r = d::lazyEquals( a, b );
    EXPECT_FALSE( r.first );
    EXPECT_FALSE( r.second );

    // size_t
    a = boost::any( (size_t)100 );
    b = boost::any( (string)&quot;200&quot; );
    r = d::lazyEquals( a, b );
    EXPECT_FALSE( r.first );
    EXPECT_FALSE( r.second );

    a = boost::any( (string)&quot;200&quot; );
    b = boost::any( (size_t)100 );
    r = d::lazyEquals( a, b );
    EXPECT_FALSE( r.first );
    EXPECT_FALSE( r.second );

    a = boost::any( (size_t)100 );
    b = boost::any( (string)&quot;200.0&quot; );
    r = d::lazyEquals( a, b );
    EXPECT_FALSE( r.first );
    EXPECT_FALSE( r.second );

    a = boost::any( (string)&quot;200.0&quot; );
    b = boost::any( (size_t)100 );
    r = d::lazyEquals( a, b );
    EXPECT_FALSE( r.first );
    EXPECT_FALSE( r.second );

    // float
    a = boost::any( (float)100 );
    b = boost::any( (string)&quot;200&quot; );
    r = d::lazyEquals( a, b );
    EXPECT_FALSE( r.first );
    EXPECT_FALSE( r.second );

    a = boost::any( (string)&quot;200&quot; );
    b = boost::any( (float)100 );
    r = d::lazyEquals( a, b );
    EXPECT_FALSE( r.first );
    EXPECT_FALSE( r.second );

    a = boost::any( (float)100 );
    b = boost::any( (string)&quot;200.0&quot; );
    r = d::lazyEquals( a, b );
    EXPECT_FALSE( r.first );
    EXPECT_FALSE( r.second );

    a = boost::any( (string)&quot;200.0&quot; );
    b = boost::any( (float)100 );
    r = d::lazyEquals( a, b );
    EXPECT_FALSE( r.first );
    EXPECT_FALSE( r.second );

    // double
    a = boost::any( (double)100 );
    b = boost::any( (string)&quot;200&quot; );
    r = d::lazyEquals( a, b );
    EXPECT_FALSE( r.first );
    EXPECT_FALSE( r.second );

    a = boost::any( (string)&quot;200&quot; );
    b = boost::any( (double)100 );
    r = d::lazyEquals( a, b );
    EXPECT_FALSE( r.first );
    EXPECT_FALSE( r.second );

    a = boost::any( (double)100 );
    b = boost::any( (string)&quot;200.0&quot; );
    r = d::lazyEquals( a, b );
    EXPECT_FALSE( r.first );
    EXPECT_FALSE( r.second );

    a = boost::any( (string)&quot;200.0&quot; );
    b = boost::any( (double)100 );
    r = d::lazyEquals( a, b );
    EXPECT_FALSE( r.first );
    EXPECT_FALSE( r.second );
}


TEST_F( DTest, Number2NotEqualsString_LazyEquals ) {
    // int
    auto a = boost::any( (int)200 );
    auto b = boost::any( (string)&quot;100&quot; );
    auto r = d::lazyEquals( a, b );
    EXPECT_FALSE( r.first );
    EXPECT_FALSE( r.second );

    a = boost::any( (string)&quot;100&quot; );
    b = boost::any( (int)200 );
    r = d::lazyEquals( a, b );
    EXPECT_FALSE( r.first );
    EXPECT_FALSE( r.second );

    a = boost::any( (int)200 );
    b = boost::any( (string)&quot;100.0&quot; );
    r = d::lazyEquals( a, b );
    EXPECT_FALSE( r.first );
    EXPECT_FALSE( r.second );

    a = boost::any( (string)&quot;100.0&quot; );
    b = boost::any( (int)200 );
    r = d::lazyEquals( a, b );
    EXPECT_FALSE( r.first );
    EXPECT_FALSE( r.second );

    // size_t
    a = boost::any( (size_t)200 );
    b = boost::any( (string)&quot;100&quot; );
    r = d::lazyEquals( a, b );
    EXPECT_FALSE( r.first );
    EXPECT_FALSE( r.second );

    a = boost::any( (string)&quot;100&quot; );
    b = boost::any( (size_t)200 );
    r = d::lazyEquals( a, b );
    EXPECT_FALSE( r.first );
    EXPECT_FALSE( r.second );

    a = boost::any( (size_t)200 );
    b = boost::any( (string)&quot;100.0&quot; );
    r = d::lazyEquals( a, b );
    EXPECT_FALSE( r.first );
    EXPECT_FALSE( r.second );

    a = boost::any( (string)&quot;100.0&quot; );
    b = boost::any( (size_t)200 );
    r = d::lazyEquals( a, b );
    EXPECT_FALSE( r.first );
    EXPECT_FALSE( r.second );

    // float
    a = boost::any( (float)200 );
    b = boost::any( (string)&quot;100&quot; );
    r = d::lazyEquals( a, b );
    EXPECT_FALSE( r.first );
    EXPECT_FALSE( r.second );

    a = boost::any( (string)&quot;100&quot; );
    b = boost::any( (float)200 );
    r = d::lazyEquals( a, b );
    EXPECT_FALSE( r.first );
    EXPECT_FALSE( r.second );

    a = boost::any( (float)200 );
    b = boost::any( (string)&quot;100.0&quot; );
    r = d::lazyEquals( a, b );
    EXPECT_FALSE( r.first );
    EXPECT_FALSE( r.second );

    a = boost::any( (string)&quot;100.0&quot; );
    b = boost::any( (float)200 );
    r = d::lazyEquals( a, b );
    EXPECT_FALSE( r.first );
    EXPECT_FALSE( r.second );

    // double
    a = boost::any( (double)200 );
    b = boost::any( (string)&quot;100&quot; );
    r = d::lazyEquals( a, b );
    EXPECT_FALSE( r.first );
    EXPECT_FALSE( r.second );

    a = boost::any( (string)&quot;100&quot; );
    b = boost::any( (double)200 );
    r = d::lazyEquals( a, b );
    EXPECT_FALSE( r.first );
    EXPECT_FALSE( r.second );

    a = boost::any( (double)200 );
    b = boost::any( (string)&quot;100.0&quot; );
    r = d::lazyEquals( a, b );
    EXPECT_FALSE( r.first );
    EXPECT_FALSE( r.second );

    a = boost::any( (string)&quot;100.0&quot; );
    b = boost::any( (double)200 );
    r = d::lazyEquals( a, b );
    EXPECT_FALSE( r.first );
    EXPECT_FALSE( r.second );
}
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://signmotion.blogspot.com/feeds/5687762901010992818/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2909062909816541374/5687762901010992818?isPopup=true' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2909062909816541374/posts/default/5687762901010992818'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2909062909816541374/posts/default/5687762901010992818'/><link rel='alternate' type='text/html' href='http://signmotion.blogspot.com/2011/12/boostany.html' title='Ленивое сравнение для boost::any()'/><author><name>Andrii</name><uri>http://www.blogger.com/profile/02715216472597824596</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjcrHHkyfsW8m8HmZZeyd2fhzwEl-shXbCxnYVY_mVq7uJpe5QET9SerP_bCPeO4YEBlXJT44IRPOcL7VtgFJsDqXwfppdES-fdokbXX0-11jdBQAyipvURKBH3N-Wh2VCye2U-W4nsp6zPgNSyi7g6gFgmmo34dH_oL_FTXf31U65BXQ/s220/Andrey-400x.png'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhAHnl9MB1PU3GLkAhENx08QOFYqqGgeEbOqex6By0gxPdS3el_YtmtyHEAoBMWnYD-KrpJJw8CBsiZEKllyH1zD0vpxLA-tEBZLxA4kicgocl3wBcfi7hV0MMTWYTvJDXxIqhqWHneqObM/s72-c/boost-any-equals.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2909062909816541374.post-9071013748729791820</id><published>2011-11-03T08:35:00.001+02:00</published><updated>2015-11-03T18:36:05.661+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="C++"/><title type='text'>Библиотека усатых шаблонов для C++</title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: left; float: left; margin-bottom: 1em; margin-right: 1em; text-align: center;&quot;&gt;
&lt;img border=&quot;0&quot; height=&quot;395&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh-S786o1GI4759cnJmglKPuT8O2r-n1nPzVql04IVlGvppdokCpg4skX6VC2UGoya8XGR0K0Rz8_ScYfM3TpJuJQZYXd-NZmE48HUWo5bP734XegvsGRVMoPd57H2Ijp840c_3okxuPbFi/s400/mustache-plustache-vcpp2010-express.png&quot; width=&quot;300&quot; /&gt;&lt;/div&gt;
Появилась необходимость использовать шаблоны в своём (инди-)проекте на C++. Т.к. я &lt;a href=&quot;http://signmotion.blogspot.com/search/label/CouchDB&quot;&gt;работаю c CouchDB&lt;/a&gt;, мне очень привычно использовать &lt;a href=&quot;http://mustache.github.com/&quot;&gt; Mustache&lt;/a&gt;. К счастью, этот замечательный и крайне быстрый шаблонизатор доступен практически для всех известных на сегодня языков программирования. C++ - известный язык :) и Mustache для него называется &lt;a href=&quot;https://github.com/mrtazz/plustache&quot;&gt;Plustache&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
Я почему решил об этом написать? Потому что работаю с C++ уже полгода (не считаю себя классным специалистом, нет), успел его и возненавидеть, и полюбить. Порог входа в этот язык - довольно высок: шишок у начинающих C++ изучать - мама не горюй! И здесь речь не о первой программе типа&amp;nbsp; &quot;&lt;a href=&quot;http://ru.wikipedia.org/wiki/Hello,_world%21&quot;&gt;Hello world!&lt;/a&gt;&quot;, хотя и это в C++ - уже достижение :) Собрать проект из исходного кода - то, без чего ни один серьёзный программист сегодня не выживет. И если человек не знает... нет, даже не основ, а (!) подноготной C++, изучение языка может замедлиться (ведь придётся писать и отлаживать свой &lt;a href=&quot;http://vexell.ru/2010/12/%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5-%D1%81%D1%82%D0%BE%D0%B8%D1%82-%D0%BB%D0%B8-%D0%B8%D0%B7%D0%BE%D0%B1%D1%80%D0%B5%D1%82%D0%B0%D1%82/&quot;&gt;велосипед&lt;/a&gt;) или даже остановиться. Надеюсь, описание процесса сборки проекта от &quot;А&quot; до &quot;Я&quot; поможет Вам в дальнейшем смело включать сторонние библиотеки в свои проекты.&lt;br /&gt;
&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
Если бы &lt;a href=&quot;https://github.com/mrtazz&quot;&gt;Daniel Schauenberg&lt;/a&gt; - 
автор Plustache, огромное ему спасибо за труд! - попробовал собрать свой
 проект под Windows, он бы, наверное, внёс изменения в код. Хотя вряд 
ли: поддерживать несколько операционных систем - та ещё радость! Тем 
более, что проект - маленький и с лёгкостью переносится на любые ОС. Прекрасно подходит для обучения. &lt;br /&gt;
&lt;br /&gt;
Итак, соберём &lt;a href=&quot;https://github.com/mrtazz/plustache&quot;&gt;Plustache&lt;/a&gt; как статическую библиотеку (*.lib) на MS Visual C++ 2010.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;span style=&quot;font-size: large;&quot;&gt;I. Получение исходного кода проекта.&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Это самый простой этап. Зайдите на &lt;a href=&quot;https://github.com/mrtazz/plustache&quot;&gt;https://github.com/mrtazz/plustache&lt;/a&gt;, скачайте ZIP-архив проекта, распакуйте содержимое.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;span style=&quot;font-size: large;&quot;&gt;II. Подготовка проекта для VC++.&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Не было бы печали, если бы &lt;a href=&quot;http://habrahabr.ru/tag/rake/&quot;&gt;rake&lt;/a&gt; работал под Windows также, как для OS X. Это не так. Хотя - клянусь! - я поставил для этой цели &lt;a href=&quot;http://rubyinstaller.org/&quot;&gt;Ruby&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;span style=&quot;font-size: large;&quot;&gt;1. Создание пустого проекта.&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Выбираем в меню VC++ &quot;Создать проект / Пустой проект &quot;...&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhn1k4Qf-1xER9v3iCyBLqtbvqsKGjMfFa-59CmVL43yXfOQMvqYg_76K3F_55XlTWxInHMNYzAO9EctOIYGT5jne5iIOQtZlmpsaZGOXOK7xf5fX3pC4VgCYHhBI9HLBmC-E5fx-jCkbSx/s1600/create-new-clear-project-vc.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;435&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhn1k4Qf-1xER9v3iCyBLqtbvqsKGjMfFa-59CmVL43yXfOQMvqYg_76K3F_55XlTWxInHMNYzAO9EctOIYGT5jne5iIOQtZlmpsaZGOXOK7xf5fX3pC4VgCYHhBI9HLBmC-E5fx-jCkbSx/s640/create-new-clear-project-vc.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
... и в свойствах проекта делаем след. изменения:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Общие / Тип конфигурации = &quot;Статическая библиотека (.lib)&quot;&lt;/li&gt;
&lt;li&gt;C++ / Общие / Обрабатывать предупреждения как ошибки = &quot;Да&quot; или &quot;Нет&quot; (см. заметку ниже). &lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;b&gt;&lt;span style=&quot;font-size: large;&quot;&gt;2. Копирование файлов.&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
VC++ поощряет создание проектов, которые заставят помучаться желающих скомпилировать их в другой &lt;a href=&quot;http://ru.wikipedia.org/wiki/IDE&quot;&gt;IDE&lt;/a&gt;. Я говорю о файлах *.h и *.cpp, которые при создании из IDE VC++ бросаются в общую папку и т.н. &quot;фильтрах&quot;, которыми VC++ мило позволяет пользоваться, но которые &lt;b&gt;не являются&lt;/b&gt; папками файловой системы. Файлы Plustache лежат в папках &quot;include&quot;, &quot;src&quot; и &quot;tests&quot;. Можно пойти на поводу у Microsoft, но здесь вовсе не тот случай, когда мы вынуждены это делать. Поэтому&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;Целиком скопируйте папки &quot;include&quot;, &quot;src&quot; и &quot;tests&quot; в папку нашего проекта, воспользовавшись Проводником Windows.&lt;/li&gt;
&lt;li&gt;Добавим в VC++ / plustache файлы, &lt;b style=&quot;color: #cc0000;&quot;&gt;(!)&lt;/b&gt; за исключением &quot;main.cpp&quot;. Будем аккуратны: h-файлы поместим в &quot;Заголовочные файлы&quot;, cpp-файлы - в &quot;Файлы исходного кода&quot;.&lt;/li&gt;
&lt;/ol&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;span style=&quot;font-size: large;&quot;&gt;3. Настройка проекта, разрешение зависимостей.&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Настроек, сделаных в п.1, недостаточно для сборки, если проект имеет зависимости. Мало какой проект на C++ их не имеет. У Plustache зависимостей две:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://boost.org/&quot;&gt;Boost&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://easy-coding.blogspot.com/search/label/gtest&quot;&gt;GoogleTest&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;b&gt;Boost&lt;/b&gt; &lt;br /&gt;
&lt;br /&gt;
За время изучения C++ я понял, что без &lt;a href=&quot;http://www.boost.org/&quot;&gt;Boost&lt;/a&gt;&#39;а программиста ждёт безрадостное существование. Если &lt;a href=&quot;http://www.boost.org/&quot;&gt;Boost&lt;/a&gt; у Вас на компьютере ещё не установлен, &lt;a href=&quot;http://www.boost.org/doc/libs/1_47_0/more/getting_started/windows.html&quot;&gt;сделайте это&lt;/a&gt;. Благо, создатели этого фреймворка пошли по пути упрощения и последние версии работают без компиляции. Вообще говоря, когда Вы начали серьёзно работать с C++, существует два ответа на вопрос &quot;Нужно ли устанавливать Boost?&quot;: (а) да, сейчас; (б) да, позже.&lt;br /&gt;
&lt;br /&gt;
&lt;b style=&quot;color: #cc0000;&quot;&gt;(!)&lt;/b&gt; После установки Boost&#39;а, убедитесь, что переменная окружения &quot;BOOST_ROOT&quot; - открываем Мой компьютер / Свойства / Дополнительно / Переменные среды - установлена и указывает на нужную папку. Например, это может быть папка &quot;&lt;i&gt;C:\boost_Версия&lt;/i&gt;&quot;.&lt;br /&gt;
Если внимательно следовали инструкции по установке, так оно и будет.&lt;br /&gt;
&lt;br /&gt;
Заходим в свойства проекта Plustache и дорисовываем:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Каталоги VC++ / Каталоги включения / Изменить / Добавить = &quot;$(BOOST_ROOT)&quot; &lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;a href=&quot;http://easy-coding.blogspot.com/2009/07/google-test.html&quot;&gt;GoogleTest&lt;/a&gt;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Если уже используете эту библиотеку &lt;a href=&quot;http://www.sql.ru/forum/actualthread.aspx?tid=843109&quot;&gt;unit-тестирования&lt;/a&gt; в других своих проектах (в Boost свой модуль тестирования тоже &lt;a href=&quot;http://www.devexp.ru/2010/01/boost-test-yunit-testirovanie-i-cmake/&quot;&gt;есть&lt;/a&gt;, но также &lt;a href=&quot;http://www.devexp.ru/2010/01/boost-test-yunit-testirovanie-i-cmake/#comment-1888&quot;&gt;есть жалобы&lt;/a&gt;, что библиотека на развивается) - просто добавьте пути к заголовочным файлам, как сделали выше для Boost&#39;а.&lt;br /&gt;
&lt;br /&gt;
Но для Plustache от GoogleTest можно отказаться. Библиотека используется в файлах папки &quot;test&quot;. Поэтому просто не добавляйте эти файлы в проект.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;span style=&quot;font-size: large;&quot;&gt;4. Устранение ошибок компиляции.&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Запускаем компиляцию. &lt;br /&gt;
&lt;br /&gt;
Первая ошибка - компилятор VC++ 2010 не найдёт пути к некоторым &lt;b&gt;своим&lt;/b&gt; же файлам включения (#include &quot;include/*.hpp&quot;). Можно&amp;nbsp; Устраняется в свойствах проекта:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Каталоги VC++ / Каталоги включения / Изменить / Добавить = &quot;Путь к папке, где лежит проект&quot;. Например, такой &amp;gt; &quot;&lt;i&gt;D:\Projects\utils\plustache&lt;/i&gt;&quot;.&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
Опция &quot;&lt;i&gt;Обрабатывать предупреждения как ошибки&lt;/i&gt;&quot; (см. выше) заставляет программиста писать &lt;b&gt;более чистый, быстрый и надёжный код&lt;/b&gt;. Для больших библиотек устанавливать эту опцию - лишняя 
головная боль, т.к. свободный код программисты на Windows пишут редко. 
Иначе, почему в &lt;a href=&quot;http://www.ogre3d.org/&quot;&gt;больших проектах&lt;/a&gt; количество предупреждений компилятора - зашкаливает!?&lt;br /&gt;
&lt;br /&gt;
Т.к. Plustache - очень маленькая библиотека, ошибок много исправлять не придётся.&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;&lt;code class=&quot;c++&quot;&gt;try {
    // ...
} catch ( int i ) {
    // ...
}
&lt;/code&gt;&lt;/pre&gt;
исправляем на&lt;br /&gt;
&lt;pre&gt;&lt;code class=&quot;c++&quot;&gt;try {
    // ...
} catch ( ... ) {
    // ...
}
&lt;/code&gt;&lt;/pre&gt;
Компилятор покажет где.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
В общем-то, на этом всё. Статическая библиотека &lt;code&gt;plustache.lib&lt;/code&gt; создана (компилятор показывает путь, куда её положил) и готова к работе в других проектах под MS&amp;nbsp;Windows. Благодаря тому, что Вы читали внимательно и не добавили в проект Visual&amp;nbsp;C++ файл &quot;main.cpp&quot;, не появится предупреждение &lt;a href=&quot;http://msdn.microsoft.com/ru-RU/library/1zzf962b%28v=VS.100%29.aspx&quot;&gt;LNK4006&lt;/a&gt; при использовании &lt;code&gt;plustache.lib&lt;/code&gt; в других проектах :) &lt;br /&gt;
&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://signmotion.blogspot.com/feeds/9071013748729791820/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2909062909816541374/9071013748729791820?isPopup=true' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2909062909816541374/posts/default/9071013748729791820'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2909062909816541374/posts/default/9071013748729791820'/><link rel='alternate' type='text/html' href='http://signmotion.blogspot.com/2011/11/mustache-c.html' title='Библиотека усатых шаблонов для C++'/><author><name>Andrii</name><uri>http://www.blogger.com/profile/02715216472597824596</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjcrHHkyfsW8m8HmZZeyd2fhzwEl-shXbCxnYVY_mVq7uJpe5QET9SerP_bCPeO4YEBlXJT44IRPOcL7VtgFJsDqXwfppdES-fdokbXX0-11jdBQAyipvURKBH3N-Wh2VCye2U-W4nsp6zPgNSyi7g6gFgmmo34dH_oL_FTXf31U65BXQ/s220/Andrey-400x.png'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh-S786o1GI4759cnJmglKPuT8O2r-n1nPzVql04IVlGvppdokCpg4skX6VC2UGoya8XGR0K0Rz8_ScYfM3TpJuJQZYXd-NZmE48HUWo5bP734XegvsGRVMoPd57H2Ijp840c_3okxuPbFi/s72-c/mustache-plustache-vcpp2010-express.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2909062909816541374.post-2536960103615957733</id><published>2011-10-28T20:19:00.000+03:00</published><updated>2015-11-03T18:34:52.637+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="CouchDB"/><title type='text'>А если в CouchDB View на View надо позарез?</title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: left; float: left; margin-bottom: 1em; margin-right: 1em; text-align: center;&quot;&gt;
&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgN91ClJQXTL1oVqc9pR9ie3RMNq8pMAKpsRLAsjz6tlNQJI9qB9tsOs_TaCjLWqLSDl-UsF8AOJ2lXrUpTrj0nfFrc0_r5Y69KR8N07kcrWKigWWBVmoRjmR-KcDh8hP353tuGldz3RLBH/s1600/view-on-view-couchdb.png&quot; /&gt;&lt;/div&gt;
Когда уже на &quot;ты&quot; с CouchDB, почти всегда оказывается, что чего-то не хватает: нет полнотекстового поиска &quot;из коробки&quot;, хранилище растёт как на дрожжах и приходится самому следить за его размером и т.д.. С поиском вопрос решается подключением &lt;a href=&quot;http://wiki.apache.org/couchdb/Full_text_search&quot;&gt;сторонних модулей&lt;/a&gt;. С пугающим ростом базы данных в след. релизах вопрос уже решён. Но вот такая хитрая штука как обработка результатов другого представления - этого в ближайших планах разработчиков CouchDB не предвидится. Хотя вещь, безусловно, полезная.&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
Например, мы можем держать в хранилище сырые данные - скажем, список фактических адресов, забитых &lt;strike&gt;кем&lt;/strike&gt; как попало - и создать для них представление (&lt;a href=&quot;http://www.job-blog.bullgare.ru/2009/08/%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80-%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D1%8B-%D1%81-view-%D0%B4%D0%BB%D1%8F-couchdb/&quot;&gt;view&lt;/a&gt;), результатом которого будет чёткая структура с разбивкой по стране / городу / индексу / улице / номеру дома и пр.. Чем хорош такой подход? Написать &lt;i&gt;идеальный&lt;/i&gt; парсер вручную введённых адресов - дело не одного дня и даже месяца (спорить с этим может только тот, кто с подобной задачей в промышленных масштабах не сталкивался). А вот &lt;i&gt;достаточный для начала работы&lt;/i&gt; парсер адресов - дело 1 часа. И это позволит начать разработку след. этапов системы без необходимости ждать полностью готового списка структурированных адресов и (!) даже когда-либо возвращаться к сырым адресам. Непробиваемые аргументы, когда работает команда и/или требуется видимый результат &quot;уже завтра&quot;. Мало? Тогда представьте, что каждый день добавляется сотня новых адресов... Потом к парсеру можно возвращаться, делая его всё лучше. Но структурированные данные благодаря созданному представлению уже на руках! И, раз уж начали представлять, предположим, что проект - большой и было принято решение оставить это живое представление (живое - потому что формирует адреса из сырого потока) как источник для других модулей системы. Т.е. менять его вывод - ни-ни!&lt;br /&gt;
&lt;br /&gt;
И вот, хотим &lt;i&gt;некоторым&lt;/i&gt; адресатам что-то сами доставлять. Для этой цели хорошо бы группировать адреса по индексам, чтобы раздать списки водителям, сэкономив и бензин, и время (Вы ведь знаете, что такое &lt;a href=&quot;http://ru.wikipedia.org/wiki/%D0%9F%D0%BE%D1%87%D1%82%D0%BE%D0%B2%D1%8B%D0%B9_%D0%B8%D0%BD%D0%B4%D0%B5%D0%BA%D1%81&quot;&gt;почтовый индекс&lt;/a&gt;). И тут CouchDB оказывается не на высоте, т.к. живой список адресов (в виде гранитного представления) - есть, а вот работать с ним - не можем: &lt;b&gt;CouchDB не поддерживает создание представления для другого представления&lt;/b&gt;.&lt;br /&gt;
&lt;br /&gt;
В общем-то, задачу подобную задачу можно решить, периодически копируя результаты работы представления в новую базу; или создав новое представление, которое помимо структурирования адресов (copy / paste здесь поможет) будет делать необходимую нам выборку и группировку по почтовым индексам. Оба решения усложнят дальнейшее сопровождение системы. А ведь как красиво задача решается простым созданием нового представления... на готовые результаты другого!&lt;br /&gt;
&lt;br /&gt;
К счастью, на этой неделе появилась разработка, позволяющая создавать цепочки представлений, благодаря которым изложенная выше задача решается и просто, и красиво &amp;gt; &lt;a href=&quot;https://github.com/afters/Couch-Incarnate&quot;&gt;https://github.com/afters/Couch-Incarnate&lt;/a&gt; &lt;br /&gt;
&lt;br /&gt;
Для своей работы требует &lt;a href=&quot;http://nodejs.org/&quot;&gt;Node.js&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
P.S. Строго говоря, &lt;a href=&quot;https://github.com/afters/Couch-Incarnate&quot;&gt;couch-incarnate&lt;/a&gt; не является единственной альтернативой реализовать представление по результатам другого map/reduce. Активно ведётся разработка целой системы - &lt;a href=&quot;https://cloudant.com/&quot;&gt;CloudAnt&lt;/a&gt; - на базе CouchDB, где, помимо прочего, поддерживается view на view что называется &quot;из коробки&quot;. &lt;a href=&quot;https://cloudant.com/&quot;&gt;CloudAnt&lt;/a&gt;, безусловно, заслуживает отдельного внимания, но это - не &lt;a href=&quot;http://couchdb.apache.org/&quot;&gt;тот&lt;/a&gt; CouchDB.
&lt;br /&gt;
&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://signmotion.blogspot.com/feeds/2536960103615957733/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2909062909816541374/2536960103615957733?isPopup=true' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2909062909816541374/posts/default/2536960103615957733'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2909062909816541374/posts/default/2536960103615957733'/><link rel='alternate' type='text/html' href='http://signmotion.blogspot.com/2011/10/couchdb-view-view.html' title='А если в CouchDB View на View надо позарез?'/><author><name>Andrii</name><uri>http://www.blogger.com/profile/02715216472597824596</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjcrHHkyfsW8m8HmZZeyd2fhzwEl-shXbCxnYVY_mVq7uJpe5QET9SerP_bCPeO4YEBlXJT44IRPOcL7VtgFJsDqXwfppdES-fdokbXX0-11jdBQAyipvURKBH3N-Wh2VCye2U-W4nsp6zPgNSyi7g6gFgmmo34dH_oL_FTXf31U65BXQ/s220/Andrey-400x.png'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgN91ClJQXTL1oVqc9pR9ie3RMNq8pMAKpsRLAsjz6tlNQJI9qB9tsOs_TaCjLWqLSDl-UsF8AOJ2lXrUpTrj0nfFrc0_r5Y69KR8N07kcrWKigWWBVmoRjmR-KcDh8hP353tuGldz3RLBH/s72-c/view-on-view-couchdb.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2909062909816541374.post-3998896086125816632</id><published>2011-10-26T16:14:00.000+03:00</published><updated>2011-10-28T20:54:34.243+03:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="CouchDB"/><title type='text'>Специфические JavaScript-функции CouchDB</title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: left; float: left; margin-bottom: 1em; margin-right: 1em; text-align: center;&quot;&gt;
&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjWvjR1eUFFqeH7uqOh8vcP9WR8Xv7jYB_x47n-Yzp0p9H6dA0CG2x7eMOeuVHPsnwi3bOiqeZq9V6pK4WuT0Fmdv9R2ZsruXlGwXy2qDfNaiwNkLSK7w8SQopSPN86LUBcDc-pxdcYh874/s1600/couchdb-function.png&quot; /&gt;&lt;/div&gt;
&lt;a href=&quot;http://ru.wikipedia.org/wiki/CouchDB&quot;&gt;CouchDB&lt;/a&gt; - &lt;b&gt;платформа&lt;/b&gt; для разработки приложений. Об этом вначале забывают веб-мастера, когда обнаруживают, что весь код пишется на JavaScript (и которые ещё не знакомы с &lt;a href=&quot;http://ru.wikipedia.org/wiki/Node.js&quot;&gt;Node.js&lt;/a&gt;, ага). Как и на любой платформе, здесь присутствуют функции, которых не найдёте в JavaScript-документации. Ниже - все они в алфавитном порядке. &lt;br /&gt;
&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
&lt;ul style=&quot;clear: both;&quot;&gt;
&lt;li&gt;&lt;a href=&quot;http://wiki.apache.org/couchdb/View_collation&quot;&gt;&lt;b&gt;emit()&lt;/b&gt;&lt;/a&gt; В &lt;a href=&quot;http://wiki.apache.org/couchdb/Introduction_to_CouchDB_views#Map_Functions&quot;&gt;map-функции&lt;/a&gt; формирует результат в виде пар ключ-значение. &lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;a href=&quot;http://wiki.apache.org/couchdb/Formatting_with_Show_and_List#Listing_Views_with_CouchDB_0.10_and_later&quot;&gt;getRow&lt;/a&gt;()&lt;/b&gt; В &lt;a href=&quot;http://guide.couchdb.org/draft/transforming.html&quot;&gt;list-функции&lt;/a&gt; позволяет обработать результат, получаемый из &lt;a href=&quot;http://guide.couchdb.org/editions/1/en/views.html&quot;&gt;view&lt;/a&gt;. &lt;/li&gt;
&lt;li&gt;&lt;b&gt;JSON.parse()&lt;/b&gt; Преобразует строку в объект &lt;a href=&quot;http://json.org/json-ru.html&quot;&gt;JSON&lt;/a&gt;. &lt;/li&gt;
&lt;li&gt;&lt;b&gt;JSON.stringify()&lt;/b&gt; Преобразует объект &lt;a href=&quot;http://json.org/json-ru.html&quot;&gt;JSON&lt;/a&gt; в строку. &lt;/li&gt;
&lt;li&gt;&lt;b&gt;log()&lt;/b&gt; Выводит в лог сообщения / значения переменных. Полезная для отладки функция. &lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://wiki.apache.org/couchdb/Formatting_with_Show_and_List#Responding_to_different_Content-Type_Request_Headers&quot;&gt;&lt;b&gt;provides()&lt;/b&gt;&lt;/a&gt; Метод, пришедший на замену respondWith(). Переопределяет заголовок перед отправкой результата клиента в &lt;a href=&quot;https://github.com/apache/couchdb/blob/1.0.1/share/www/script/test/show_documents.js#L137-157&quot;&gt;show / view&lt;/a&gt;. &lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;a href=&quot;http://wiki.apache.org/couchdb/Formatting_with_Show_and_List#Responding_to_different_Content-Type_Request_Headers&quot;&gt;registerType()&lt;/a&gt;&lt;/b&gt; Добавляет новый тип, который может быть возвращён в заголовке ответа. Посмотреть предустановленные типы Вы можете в &lt;code&gt;&amp;lt;ПапкеCouchDB&amp;gt;/share/couchdb/server/main.js&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://caolanmcmahon.com/posts/commonjs_modules_in_couchdb&quot;&gt;&lt;b&gt;require()&lt;/b&gt;&lt;/a&gt; Подключает указанный JavaScript-файл (стандарт &lt;a href=&quot;http://www.commonjs.org/&quot;&gt;CommonJS&lt;/a&gt;). &lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;a href=&quot;http://wiki.apache.org/couchdb/Formatting_with_Show_and_List#Listing_Views_with_CouchDB_0.10_and_later&quot;&gt;send()&lt;/a&gt;&lt;/b&gt; Отправляет клиенту пакет или часть пакета. Используется в &lt;a href=&quot;http://guide.couchdb.org/draft/transforming.html&quot;&gt;list-функции&lt;/a&gt;. &lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://wiki.apache.org/couchdb/Formatting_with_Show_and_List#Listing_Views_with_CouchDB_0.10_and_later&quot;&gt;&lt;b&gt;start()&lt;/b&gt;&lt;/a&gt; Задаёт заголовок для пакета в list-функции. Всегда должна идти раньше &lt;b&gt;send()&lt;/b&gt;. &lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;a href=&quot;http://stackoverflow.com/questions/7306981/how-to-get-sum-of-all-couchdb-values&quot;&gt;sum()&lt;/a&gt;&lt;/b&gt; Суммирует значения в reduce-функции.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;toJSON()&lt;/b&gt; Псевдоним для &lt;b&gt;JSON.stringify()&lt;/b&gt;.&lt;/li&gt;
&lt;/ul&gt;
Ссылался я на страницы, которые посчитал наиболее удачными для понимания работы описываемых функций. Поэтому, если в первом абзаце не найдёте ожидаемое упоминание функции, просто посмотрите ниже: непременно обнаружите примеры / пояснения.</content><link rel='replies' type='application/atom+xml' href='http://signmotion.blogspot.com/feeds/3998896086125816632/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2909062909816541374/3998896086125816632?isPopup=true' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2909062909816541374/posts/default/3998896086125816632'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2909062909816541374/posts/default/3998896086125816632'/><link rel='alternate' type='text/html' href='http://signmotion.blogspot.com/2011/10/javascript-couchdb.html' title='Специфические JavaScript-функции CouchDB'/><author><name>Andrii</name><uri>http://www.blogger.com/profile/02715216472597824596</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjcrHHkyfsW8m8HmZZeyd2fhzwEl-shXbCxnYVY_mVq7uJpe5QET9SerP_bCPeO4YEBlXJT44IRPOcL7VtgFJsDqXwfppdES-fdokbXX0-11jdBQAyipvURKBH3N-Wh2VCye2U-W4nsp6zPgNSyi7g6gFgmmo34dH_oL_FTXf31U65BXQ/s220/Andrey-400x.png'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjWvjR1eUFFqeH7uqOh8vcP9WR8Xv7jYB_x47n-Yzp0p9H6dA0CG2x7eMOeuVHPsnwi3bOiqeZq9V6pK4WuT0Fmdv9R2ZsruXlGwXy2qDfNaiwNkLSK7w8SQopSPN86LUBcDc-pxdcYh874/s72-c/couchdb-function.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2909062909816541374.post-3812200134599032603</id><published>2011-10-19T22:11:00.002+03:00</published><updated>2015-11-03T18:34:00.924+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="CouchDB"/><title type='text'>CouchDB 1.1.1: Релиз близок!</title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: left; float: left; margin-bottom: 1em; margin-right: 1em; text-align: center;&quot;&gt;
&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhxxjubbqZCGfeyTkTsskjQ9VK5Jg-WnDiukBDBfq6-yoG4-CTG6hQB5UbVt4fjntH6PeSRugWRkup9GwuWLLyZT9eDe6jAyh4gA_jtgrpiV06opzlCY3iyci5iSeXl8YHy5VPzaFQ6sm1r/s1600/build-vote-reliaze-couchdb.png&quot; /&gt;&lt;/div&gt;
Сегодня &lt;a href=&quot;http://permalink.gmane.org/gmane.comp.db.couchdb.devel/17616&quot;&gt;собран пререлиз CouchDB&amp;nbsp;1.1.1&lt;/a&gt;.&lt;br /&gt;
(Последняя официальная версия CouchDB - 1.1.0 - была выпущена 30-05-2011&amp;nbsp;г.)&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;span style=&quot;font-size: large;&quot;&gt;Добавлена функциональность&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://signmotion.blogspot.com/2011/09/couchdb-ubuntu.html&quot;&gt;Наконец-то&lt;/a&gt;, CouchDB дружит со SpiderMonkey 1.8.5!&lt;/li&gt;
&lt;li&gt;Добавлена настройка (размер результата в байтах) в файл конфигурации для &lt;a href=&quot;http://localhost/_log&quot;&gt;http://localhost/_log&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Модулю &lt;a href=&quot;http://commonjs.org/&quot;&gt;CommonJS&lt;/a&gt; разрешено быть пустым.&lt;/li&gt;
&lt;li&gt; Etag&#39;и для представлений стали умнее.&lt;/li&gt;
&lt;li&gt;Улучшен обработчик, определяющий количество открытых баз (параметр конфигурации &lt;code&gt;max_dbs_open_limit&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;В ответе для JSONP теперь передаётся &quot;Content-Type&quot;: &quot;text/javascript&quot;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://wiki.apache.org/couchdb/Document_Update_Handlers&quot;&gt;Обработчик обновлений&lt;/a&gt; может возвращать HTTP-код в ответе клиенту.&lt;/li&gt;
&lt;li&gt;При очистке представлений (сжатии), удаляются все индексные файлы, если в базе отсутствует &lt;a href=&quot;http://guide.couchdb.org/draft/design.html&quot;&gt;ddoc&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Для параметра конфигурации &lt;code&gt;max_replication_retry_count&lt;/code&gt; теперь можно указать &quot;бесконечность&quot;. См. прим. в файле конфигурации.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;/ul&gt;
&lt;b&gt;&lt;span style=&quot;font-size: large;&quot;&gt;Исправлены ошибки&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Запускалась &lt;code&gt;validate_doc_update&lt;/code&gt; функция, даже если она была удалена.&lt;/li&gt;
&lt;li&gt;В &lt;code&gt;_changes&lt;/code&gt; попадались дубликаты.&lt;/li&gt;
&lt;li&gt;Обработчик обновлений прекращал работу после разрешения конфликта.&lt;/li&gt;
&lt;li&gt;Включение фильтра в &lt;code&gt;_replicator&lt;/code&gt; могло повредить базу.&lt;/li&gt;
&lt;li&gt;Сжатие большого представления завершалось с ошибкой.&lt;/li&gt;
&lt;li&gt;При каждом вызове &lt;code&gt;_log&lt;/code&gt; создавался новый дескриптор файла.&lt;/li&gt;
&lt;li&gt;Терялись записи при вызове &lt;code&gt;_changes?style=all_docs&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;В системе оставались жить процессы couchjs, которые завершались с ошибкой &lt;code&gt;reduce_overflow&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Метод &lt;code&gt;&lt;a href=&quot;http://www.blogger.com/&quot;&gt;&lt;span id=&quot;goog_1844213449&quot;&gt;&lt;/span&gt;provides()&lt;span id=&quot;goog_1844213450&quot;&gt;&lt;/span&gt;&lt;/a&gt;&lt;/code&gt; не корректно работал в &lt;code&gt;show&lt;/code&gt;. &lt;a href=&quot;https://issues.apache.org/jira/browse/COUCHDB-1272&quot;&gt;CouchDB-1272&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Репликация прекращалась, когда в базе-источнике встречался документ с пустым UID.&lt;/li&gt;
&lt;li&gt;Процесс couchjs мог зависать при обслуживании некоторых запросов.&lt;/li&gt;
&lt;li&gt;Исправлены ошибки в &lt;a href=&quot;http://wiki.apache.org/couchdb/HTTP_Document_API?highlight=%28multipart%29%7C%28PUT%29%7C%28API%29#Attachments&quot;&gt;multipart PUT API&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;/ul&gt;
&lt;b&gt;&lt;span style=&quot;font-size: large;&quot;&gt;Прочие мелочи&lt;/span&gt;&lt;/b&gt; &lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Минимальная версия Erlang&#39;а - R13B02. &lt;/li&gt;
&lt;li&gt;Для Windows-версии добавлена ссылка на &lt;a href=&quot;http://icu-project.org/download/4.2.html&quot;&gt;ICU 4.2&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Путь для функций обновления может начинаться со слешей.&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;/ul&gt;
</content><link rel='replies' type='application/atom+xml' href='http://signmotion.blogspot.com/feeds/3812200134599032603/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2909062909816541374/3812200134599032603?isPopup=true' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2909062909816541374/posts/default/3812200134599032603'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2909062909816541374/posts/default/3812200134599032603'/><link rel='alternate' type='text/html' href='http://signmotion.blogspot.com/2011/10/couchdb-111.html' title='CouchDB 1.1.1: Релиз близок!'/><author><name>Andrii</name><uri>http://www.blogger.com/profile/02715216472597824596</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjcrHHkyfsW8m8HmZZeyd2fhzwEl-shXbCxnYVY_mVq7uJpe5QET9SerP_bCPeO4YEBlXJT44IRPOcL7VtgFJsDqXwfppdES-fdokbXX0-11jdBQAyipvURKBH3N-Wh2VCye2U-W4nsp6zPgNSyi7g6gFgmmo34dH_oL_FTXf31U65BXQ/s220/Andrey-400x.png'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhxxjubbqZCGfeyTkTsskjQ9VK5Jg-WnDiukBDBfq6-yoG4-CTG6hQB5UbVt4fjntH6PeSRugWRkup9GwuWLLyZT9eDe6jAyh4gA_jtgrpiV06opzlCY3iyci5iSeXl8YHy5VPzaFQ6sm1r/s72-c/build-vote-reliaze-couchdb.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2909062909816541374.post-4882752969078204948</id><published>2011-10-16T19:12:00.000+03:00</published><updated>2011-10-19T22:13:25.603+03:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Couchbase"/><category scheme="http://www.blogger.com/atom/ns#" term="CouchDB"/><title type='text'>Couchbase Server 2.0 &gt; Общие вопросы и ответы (по итогам вебинара)</title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: left; float: left; margin-bottom: 1em; margin-right: 1em; text-align: center;&quot;&gt;
&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0-_ka-Rj7u8DWhj5E66BvdRMEATl5pyrJ12eTesjgDx7mTfYdt4c4_PxXsRCDdjp5lMy186ft2rocfuokkG5cypgU1s7QqbOHVHkk8BAGTwvfGhuGXnBJfJXogFhPrbAiVAnkHwwLNfhM/s1600/couchbase-server-2.png&quot; /&gt;&lt;/div&gt;
&lt;i&gt;Перевод итогов вебинаров &lt;/i&gt;&lt;a href=&quot;http://couchbase.org/&quot;&gt;&lt;i&gt;Couchbase&lt;/i&gt;&lt;/a&gt;&lt;i&gt;, которые на этой неделе опубликовал Perry Krug. &lt;a href=&quot;http://blog.couchbase.com/couchbase-server-20-most-common-questions-and-answers&quot;&gt;Источник&lt;/a&gt;.&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;div style=&quot;color: #999999;&quot;&gt;
&lt;span style=&quot;font-size: x-small;&quot;&gt;I just finished up a nine-week technical webinar series highlighting the
 features of our upcoming release of Couchbase Server 2.0. It was such a
 blast interacting with the hundreds of participants, and I was blown 
away by the level of excitement, engagement and anticipation for this 
new product.&lt;/span&gt;&lt;/div&gt;
Я (&lt;i&gt;чит. - Пэри Круг&lt;/i&gt;) только что закончил 9-недельную серию вебинаров, освещающих новые возможности предстоящего релиза Couchbase Server 2.0. Это были яркие беседы с сотнями участников и я просто обалдел от волнения, рассказывая о новом продукте и ожидая его выпуска.&lt;br /&gt;
&lt;br /&gt;
&lt;div style=&quot;color: #999999;&quot;&gt;
&lt;span style=&quot;font-size: x-small;&quot;&gt;(By the way, if you missed the series, all nine sessions are &lt;a href=&quot;http://www.couchbase.com/on-demand/webinar/couchbase-server-2.0-overview&quot;&gt;available for replay&lt;/a&gt;).&lt;/span&gt;&lt;/div&gt;
(Если Вы пропустили серии, записи всех  вебинаров находятся &lt;a href=&quot;http://www.couchbase.com/on-demand/webinar/couchbase-server-2.0-overview&quot;&gt;здесь&lt;/a&gt;).&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;color: #999999; font-size: x-small;&quot;&gt;There were some great questions generated by users throughout the 
webinar series, and my original plan was to use this blog entry to 
highlight them all. I quickly realized there were too many to expect 
anyone to read through all of them, so I’ve taken a different tack. This
 blog will feature the most common/important/interesting questions and 
answer them here for everyone’s benefit. Before diving in, I’ll answer 
the question that was by far the most commonly asked: “How long until 
the GA of Couchbase Server 2.0?” We are currently on track to release it
 before the end of the year. In the meantime, please feel free to 
experiment with the &lt;a href=&quot;http://www.couchbase.org/get/couchbase/2.0.0&quot;&gt;Developer Preview&lt;/a&gt; that is already available. As for the rest of the questions, here goes! &lt;/span&gt;&lt;br /&gt;
Участники задавали хорошие вопросы и  цель этого текста - собрать вопросы и ответы вместе, в этом блоге. Что я и сделал довольно быстро. Здесь будут освещены наиболее общие / важные / интересные вопросы и ответы на них. Но вначале, я отвечу на самый общий вопрос: &quot;Когда появится официальная Couchbase Server 2.0?&quot; Мы ожидаем её появления до конца года. Тем временем, пожалуйста, свободно эксперементируйте с &lt;a href=&quot;http://www.couchbase.org/get/couchbase/2.0.0&quot;&gt;версией для разработчиков&lt;/a&gt;, она уже доступна. Приступим!&lt;br /&gt;
&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
&lt;span style=&quot;color: #999999; font-size: x-small;&quot;&gt;Q: What are the primary benefits of incorporating Membase and&amp;nbsp;CouchDB into a single product?&lt;/span&gt; &lt;br /&gt;
&lt;b&gt;В&amp;gt; Какие основные преимущества включения Membase и CouchDB в один проект?&amp;nbsp;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;div style=&quot;color: #999999;&quot;&gt;
&lt;span style=&quot;font-size: x-small;&quot;&gt;A: Membase is a super fast, highly scalable key value store known for 
its performance and scalability. CouchDB on the other hand is a great 
document database, with powerful indexing and querying capabilities. 
Combining these two products brings together the best of both worlds to 
create a high-performance, highly elastic NoSQL database that scales out
 linearly while providing querying, indexing and document-oriented 
features.&lt;/span&gt;&lt;/div&gt;
О&amp;gt; Membase - очень быстрое, масштабируемое хранилище &quot;Ключ-Значение&quot;. CouchDB - великолепная документоориентированная база данных, с мощными возможностями индексации и построения выборок. Объединение этих двух продуктов позволяет создать высокопроизводительное, гибкое NoSQL-хранилище, обеспечивающее нас линейной сложностью при масштабировании плюс возможностями индексации и выборки документов.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;div style=&quot;color: #999999;&quot;&gt;
&lt;span style=&quot;font-size: x-small;&quot;&gt;Q: Does Couchbase speed up access to a database document by automatically caching it in memory?&lt;/span&gt;&lt;/div&gt;
&lt;b&gt;В&amp;gt; Действительно ли увеличивается скорость работы с документами при  кешировании данных в памяти?&lt;/b&gt; &lt;br /&gt;
&lt;br /&gt;
&lt;div style=&quot;color: #999999;&quot;&gt;
&lt;span style=&quot;font-size: x-small;&quot;&gt;A: Absolutely! That’s one of the great feature of Couchbase Server 2.0, 
and comes from the vast experience we have with memcached. All access to
 documents goes through our integrated RAM caching layer (built out of 
memcached) to provide extremely low and, more importantly, predictable, 
latency under extremely heavy loads. For instance, we regularly see 
customers well over 100k operations/sec across a cluster and have taken 
single nodes to over 200k operations/sec in our own testing 
environments. This RAM caching layer also allows us to handle spikes in 
write (and read) load without affecting the performance of the 
application.&lt;/span&gt;&lt;/div&gt;
О&amp;gt; Так и есть! Это одно из больших достижений Couchbase Server 
2.0, и пришло оно благодаря нашему огромному опыту работы с Membase. Любой доступ к документам происходит через интегрированный кеш, RAM-слой (строится с помощью &#39;memcached&#39;), что даёт крайне низкую и, что более важно, предсказуемую задержку в высоконагруженных системах. Например, мы сейчас получаем более чем 100K операций/сек на целом кластере, а в нашей тестовой среде смогли достичь производительности до 200K операций/сек для одного узла. Слой кеширования также позволяет нам обходить проблемы при записи (и чтении) без потери производительности приложения.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;div style=&quot;color: #999999;&quot;&gt;
&lt;span style=&quot;font-size: x-small;&quot;&gt;Q: I see in your forums that Couchbase Server 2.0 uses the memcached 
protocol for accessing data as this is compatible for existing Membase 
users and also for the much higher performance. Is there a way to use 
REST APIs akin to CouchDB’s to access the documents in Couchbase Server 
2.0?&lt;/span&gt;&lt;/div&gt;
&lt;b&gt;В&amp;gt; Я вижу на вашем форуме, что Couchbase Server 2.0 использует протокол memcached для доступа к данным для совместимости с уже существующими Membase-клиентами плюс для увеличения производительности. Как же тогда пользоваться REST API, который предоставляет CouchDB для доступа к документам?&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;div style=&quot;color: #999999;&quot;&gt;
&lt;span style=&quot;font-size: x-small;&quot;&gt;A: The first version of Couchbase Server 2.0 uses the memcached 
protocol for document access, and the CouchDB HTTP protocol for 
accessing views. Over time, these two will merge even closer. In the 
meantime, we have provided a number of client libraries that abstract 
these two access methods away from the developer.&lt;/span&gt;&lt;/div&gt;
О&amp;gt; Первая версия Couchbase Server 2.0 использует memcached-протокол для доступа к документам и HTTP-протокол для доступа к представлениям CouchDB. Со временем это будет объединено. Пока что мы создали библиотеки, которые объединяют эти два метода доступа к данным.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;div style=&quot;color: #999999;&quot;&gt;
&lt;span style=&quot;font-size: x-small;&quot;&gt;Q: Is Couchbase Server 2.0 going to be open source?&lt;/span&gt;&lt;/div&gt;
&lt;b&gt;В&amp;gt; Couchbase Server 2.0 будет OpenSource-проектом?&lt;/b&gt; &lt;br /&gt;
&lt;br /&gt;
&lt;div style=&quot;color: #999999;&quot;&gt;
&lt;span style=&quot;font-size: x-small;&quot;&gt;A: It already is! As a company, Couchbase is fully committed to the 
furthering of the open source communities that exist and are being built
 around our various products. While our focus is on providing 
enterprise-class software to our paying customers, we embrace the 
free-flow of ideas and wide adoption that an open source project allows 
for and believe very strongly that there is a place for both.&lt;/span&gt;&lt;/div&gt;
О&amp;gt; Он уже им является! Как организация, Couchbase полностью представлена в сообществе OpenSource и на основе Couchbase Server 2.0 могут создаваться свои вариации продукта. Несмотря на то, что мы сосредоточены на приложениях класса предприятия, мы открыты для идей и верим, что благодаря OpenSource система будет адаптирована и для других областей. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;color: #999999;&quot;&gt;Indexing/Querying&lt;/span&gt;&lt;br /&gt;
&lt;b&gt;&lt;span style=&quot;font-size: large;&quot;&gt;Индексация / Выборка&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;span style=&quot;font-size: large;&quot;&gt;&amp;nbsp;&lt;/span&gt;
&lt;br /&gt;
&lt;div style=&quot;color: #999999;&quot;&gt;
&lt;span style=&quot;font-size: x-small;&quot;&gt;Q: All I need is a simple secondary index, not map/reduce...how do I do that?&lt;/span&gt;&lt;/div&gt;
&lt;b&gt;В&amp;gt; Всё что мне нужно, это просто вторичный индекс, не map/reduce... Как мне быть?&lt;/b&gt; &lt;br /&gt;
&lt;br /&gt;
&lt;div style=&quot;color: #999999;&quot;&gt;
&lt;span style=&quot;font-size: x-small;&quot;&gt;A: Currently, all of our indexes are built using a map function (the 
reduce is totally optional and can be ignored here). &amp;nbsp;This is really 
just another syntax for creating an index and there are a variety of 
examples avialable discussing how to create very simple indexes. &amp;nbsp;The 
very simplest form would involve just putting &quot;emit(doc.&lt;field&gt;)&quot; 
in your map function where &lt;field&gt; is what you want to index off 
of. &amp;nbsp;This will create a list of all documents containing that field, 
sorted by that field. &amp;nbsp;Of course there are more complex scenarios, but 
it can be made quite simple if that is what is needed.&lt;/field&gt;&lt;/field&gt;&lt;/span&gt;&lt;/div&gt;
&lt;field&gt;&lt;field&gt;О&amp;gt;&amp;nbsp; В настоящее время все индексы строятся используя map-функцию (reduce можно игнорировать). Это просто другой синтаксис для создания индекса и есть множество разных примеров, как создать очень простые индексы. Самое простое  - поместить emit( doc.field ) в Вашу map-функцию. Это создаст список всех документов, содержащих поле &#39;field&#39;; список будет сразу отсортирован по этому полю. Конечно, в действительности приходится сталкиваться с более сложными сценариями, но строится индекс всегда очень просто, если знаете, что Вам нужно. &lt;/field&gt;&lt;/field&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;div style=&quot;color: #999999;&quot;&gt;
&lt;span style=&quot;font-size: x-small;&quot;&gt;Q: How does dealing with Couchbase Server 2.0 views differ from CouchDB and Couchbase Single Server?&lt;/span&gt;&lt;/div&gt;
&lt;b&gt;В&amp;gt; Чем представления Couchbase Server 2.0 отличаются от CouchDB и Couchbase Single Server? &lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;div style=&quot;color: #999999;&quot;&gt;
&lt;span style=&quot;font-size: x-small;&quot;&gt;A: Not at all...the format, the syntax, everything is the same. 
&amp;nbsp;Additionally, all the options for querying are supported. &amp;nbsp;You can 
literally copy-paste the view code from one to another. &amp;nbsp;Multiple design
 docs are also supported.&lt;/span&gt;&lt;/div&gt;
О&amp;gt; Ничем... Формат, синтаксис, всё остальное - одинаково. В дополнение, все опции запросов поддерживаются. Вы можете буквально копировать код представления из одной системы в другую. Множество дизайн-документов также поддерживается.&amp;nbsp; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;div style=&quot;color: #999999;&quot;&gt;
&lt;span style=&quot;font-size: x-small;&quot;&gt;Q: Does Couchbase Server 2.0 support ad-hoc querying?&lt;/span&gt;&lt;/div&gt;
&lt;b&gt;В&amp;gt; Couchbase Server 2.0 поддерживает запросы по требованию (&lt;a href=&quot;http://ru.wikipedia.org/wiki/%D0%91%D0%B5%D1%81%D0%BF%D1%80%D0%BE%D0%B2%D0%BE%D0%B4%D0%BD%D1%8B%D0%B5_ad_hoc_%D1%81%D0%B5%D1%82%D0%B8&quot;&gt;ad-hoc&lt;/a&gt; запросы)? &lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;div style=&quot;color: #999999;&quot;&gt;
&lt;span style=&quot;font-size: x-small;&quot;&gt;A: At the moment, all querying to Couchbase Server (like CouchDB) 
must be done against pre-materialized views. In general, this is the 
only way of providing reliable performance when making those queries. We
 also understand the need to for more on-demand/ad-hoc querying and are 
working diligently to provide that as well. Couchbase has already begun 
to take an industry-leader approach to creating a language specifically 
for unstructured data that can be used across the NoSQL landscape. Take a
 look at &lt;a href=&quot;http://unqlspec.org/&quot; title=&quot;http://unqlspec.org&quot;&gt;http://unqlspec.org&lt;/a&gt; to see what we&#39;re working on!&lt;/span&gt;&lt;/div&gt;
О&amp;gt; В данный момент все запросы к Couchbase Server (аналогично - к CouchDB) должны быть предварительно воплощены в представлениях. В общем, это только способ получить надёжную работу этих запросов. Мы также понимаем необходимость создания запросов по требованию и старательно работаем, чтобы это тоже было. Couchbase уже начали воспринимать как отраслевого лидера, создающего язык специально для работы с неструктурированными данными. Взгляните по &lt;a href=&quot;http://unqlspec.org/&quot; title=&quot;http://unqlspec.org&quot;&gt;http://unqlspec.org&lt;/a&gt; - и увидите, что работы идут полным ходом!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;color: #999999;&quot;&gt;SDKs/Client Libraries&lt;/span&gt;&lt;br /&gt;
&lt;b&gt;&lt;span style=&quot;font-size: large;&quot;&gt;Среды разработки / Клиентские библиотеки&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;span style=&quot;font-size: large;&quot;&gt;&amp;nbsp;&lt;/span&gt;
&lt;br /&gt;
&lt;div style=&quot;color: #999999;&quot;&gt;
&lt;span style=&quot;font-size: x-small;&quot;&gt;Q: Which SDK&#39;s and client libraries are supported?&lt;/span&gt;&lt;/div&gt;
&lt;b&gt;В&amp;gt; Какие SDK и клиентские библиотеки поддерживаются? &lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;color: #999999; font-size: x-small;&quot;&gt;A: At a base level, Couchbase Server 2.0 supports any library that 
implements the memcached protocol (and there are MANY of those). &amp;nbsp;For 
the additional functionality that we have added (extended protocol 
commands and view access) Couchbase &lt;a href=&quot;http://couchbase.org/code&quot;&gt;provides client libraries&lt;/a&gt;
 for a variety of languages (Java, .NET, PHP, Python, Ruby, C/C++) as 
well as instructions for how to extend libraries for other languages.&lt;/span&gt;&lt;br /&gt;
О&amp;gt; На базовом уровне, Couchbase Server 2.0 поддерживаются библиотеки, которые реализуют протокол Memcached (и таких много). Для расширения функциональности, мы добавили библиотеки на разных языках программирования (Java, .NET, PHP, Python, Ruby, C/C++) а также руководства, как создать библиотеку на других языках. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;div style=&quot;color: #999999;&quot;&gt;
&lt;span style=&quot;font-size: x-small;&quot;&gt;Q: Is there any chance of dogpiling with stale=update_after? If you 
get 30 requests simultaneously for a view with stale=update_after, will 
they generate several requests simultaneously for updating the index?&lt;/span&gt;&lt;/div&gt;
&lt;b&gt;В&amp;gt; Есть возможность создать беспорядок при использовании stale=update_after? Если вы получаете одновременно 30 запросов для обновления с включённым stale=update_after, тогда будут генерироваться разные запросы при обновлении индекса? &lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;div style=&quot;color: #999999;&quot;&gt;
&lt;span style=&quot;font-size: x-small;&quot;&gt;A: To recap, “stale” tells the server that this query request should 
be returned as quickly as possible, knowing that some data that has 
already been written may not be included in the view.&amp;nbsp; By putting 
“update_after” in the request as well, the client is telling the server 
to rematerialize the index in the background…after returning the initial
 request as quickly as possible.&amp;nbsp; Once this rematerialization is 
started, subsequent requests will not cause anything different to happen
 so there’s no worry of “dogpiling” or “stampeding herd” issues.&lt;/span&gt;&lt;/div&gt;
О&amp;gt; Вспомним, &#39;stale&#39; говорит серверу что ответ на этот запрос должен быть возвращён так быстро, насколько возможно. Это означает, что некоторые данные, которые были записаны в хранилище, могут не попасть в представление. Поставив &#39;update_after&#39; в запрос, клиент говорит серверу перестраивать индекс в фоне... после возвращения начального запроса так быстро, насколько возможно. Раз построение индекса началось, последующие запросы не вызовут ничего. Так что не волнуйтесь о беспорядке в базе (в ориг. - dogpilling or stampeding herd, &quot;собачей кучи&quot; или &quot;панического бегства стада&quot;). &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;div style=&quot;color: #999999;&quot;&gt;
&lt;span style=&quot;font-size: x-small;&quot;&gt;Q: How does the client know when to pull updated the server/vbucket maps?&lt;/span&gt;&lt;/div&gt;
&lt;b&gt;В&amp;gt; Как клиент узнает, что обновление на сервере завершилось? &lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;div style=&quot;color: #999999;&quot;&gt;
&lt;span style=&quot;font-size: x-small;&quot;&gt;A: All clients (whether they be our “smart” clients or are going 
through our Moxi process) will maintain a streaming connection to a 
Couchbase Server.&amp;nbsp; When the topology of the cluster changes 
(add/remove/failover nodes), the clients will be automatically updated 
with a new vbucket map over this connection.&amp;nbsp; The clients can also 
request this map on-demand, and do so everytime they startup.&amp;nbsp; 
Additionally, each node of the cluster knows which vbuckets it is 
responsible for and will only return data for those vbuckets.&amp;nbsp; This way,
 even if a client is temporarily out of sync with the cluster, it will 
never be vulnerable to inconsistent data.&lt;/span&gt;&lt;/div&gt;
О&amp;gt; Все клиенты (будь это наши &quot;умные&quot; клиенты или идущие через наш &lt;a href=&quot;http://www.couchbase.org/wiki/display/membase/Moxi&quot;&gt;Moxi&lt;/a&gt;-процесс) будут поддерживать потоковое соединение с 
Couchbase Server. Когда топология кластера изменится (добавятся / удалятся / откажут узлы), клиент будет автоматически извещён по этому соединению получение новой &lt;a href=&quot;http://www.couchbase.org/wiki/display/membase/vBuckets&quot;&gt;vbucket&lt;/a&gt;-карты. Клиенты также могут самостоятельно отправить запрос этой карты и делать это каждый раз при подключении. Кроме того, каждый узел кластера знает какие vbacket за что отвечают и может вернуть данные для конкретных vbucket. Т.о., даже если клиент временно не синхронизирован с кластером, он никогда не будет уязвим к получению противоречивых данных. &amp;nbsp; &amp;nbsp; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;color: #999999;&quot;&gt;Development/Production View Usage&lt;/span&gt;&lt;br /&gt;
&lt;b&gt;&lt;span style=&quot;font-size: large;&quot;&gt;Использование представлений при разработке / в производстве&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;span style=&quot;font-size: large;&quot;&gt;&amp;nbsp;&lt;/span&gt;
&lt;br /&gt;
&lt;div style=&quot;color: #999999;&quot;&gt;
&lt;span style=&quot;font-size: x-small;&quot;&gt;Q: Why the extra effort of creating a view in “development” mode and then pushing it to production?&lt;/span&gt;&lt;/div&gt;
&lt;b&gt;В&amp;gt; Почему нужны дополнительные усилия для создания представлений в режиме &quot;разработки&quot; и когда внедряем представления на стадии &quot;производства&quot;? &lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;div style=&quot;color: #999999;&quot;&gt;
&lt;span style=&quot;font-size: x-small;&quot;&gt;A: We wanted to provide the ability to do view development on a live 
dataset, but didn’t want to have that development impact the currently 
running application.&amp;nbsp; Thus, a “development” mode was created so that 
users could create and edit views on “real” data.&amp;nbsp; In order to speed up 
the iterations of development, the default is to materialize a view over
 a subset of the data.&amp;nbsp; When the development is complete, the user can 
opt to materialize the view over the whole cluster right before pushing 
it to production.&amp;nbsp; This gives the added benefit of materializing the 
view so that it is immediately ready for the application to use.&amp;nbsp; 
Lastly, this “development” mode can be used to edit views that are 
currently in production , without affecting the application’s access to 
them (by making a copy).&amp;nbsp; When the edits are complete, the view can then
 be materialized and swapped with the original into production.&lt;/span&gt;&lt;/div&gt;
О&amp;gt; Мы хотели бы предоставить возможность строить представления на живых наборах данных, но не хотим влиять при разработке на работающее сейчас приложение. Т.о., режим &quot;разработки&quot; был создан: так пользователи могли бы создавать и редактировать представления на &quot;реальных&quot; данных. В целях ускорения итераций разработки, по умолчанию представления создаются над подмножеством данных. Когда разработка завершена, пользователь может разместить представление на целом кластере прямо перед запуском на живых данных. Это даёт дополнительное преимущество: представление готово к немедленному использованию в приложении. Наконец, этот режим &quot;разработки&quot; может быть использован для редактирования представлений, находящихся в &quot;производстве&quot;, без затрагивания самого приложения (сделав копию). Когда редактирование завершено, новое представление может заменить оригинал на &quot;производстве&quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;div style=&quot;color: #999999;&quot;&gt;
&lt;span style=&quot;font-size: x-small;&quot;&gt;Q: How do you control what the development data set is?&lt;/span&gt;&lt;/div&gt;
&lt;b&gt;В&amp;gt; Как контролировать, что работаем с &quot;данными для разработки&quot;?&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;div style=&quot;color: #999999;&quot;&gt;
&lt;span style=&quot;font-size: x-small;&quot;&gt;A:&amp;nbsp; Currently, the development dataset is automatically decided by 
the software depending on how much data exists.&amp;nbsp; For small datasets, the
 software will actually materialize the view across the whole thing. As 
that gets larger, the software will automatically scale it down to 
provide a quicker response time while developing. Once the view is 
finalized, the user has the option to run it over the whole dataset 
manually (by clicking the tab “Full Cluster Dataset”) both for the 
purposes of final verification and to prepare it for production use.&lt;/span&gt;&lt;/div&gt;
О&amp;gt; На сегодня, набор данных для разработки автоматически определяется приложением&amp;nbsp; в зависимости от объёма существующих данных. Для малых наборов, приложение будет создавать представление, включив все данные. Для больших наборов, приложение автоматически масштабирует наборы, опираясь на время отклика при их получении. По завершении разработки представления, пользователь имеет возможность вручную запустить код для всего набора (щёлкнув по вкладке &quot;Full Cluster Dataset&quot;) с целью окончательной проверки и подготовки представления для использования в &quot;производстве&quot;. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;color: #999999;&quot;&gt;Clustering&lt;/span&gt;&lt;br /&gt;
&lt;b&gt;&lt;span style=&quot;font-size: large;&quot;&gt;Кластеризация&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;span style=&quot;font-size: large;&quot;&gt;&amp;nbsp;&lt;/span&gt;
&lt;br /&gt;
&lt;div style=&quot;color: #999999;&quot;&gt;
&lt;span style=&quot;font-size: x-small;&quot;&gt;Q: For a bucket with replica and auto-failover, will a server failure
 without rebalance causing retrieval/update errors on that bucket?&lt;/span&gt;&lt;/div&gt;
&lt;b&gt;В&amp;gt; Для пакета (bucket) с репликой и при включённой &quot;автоматической отказоусточивости&quot;, сбой пройдёт без перебалансировки кластера в случае ошибки выборки / обновления в пакете?&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;div style=&quot;color: #999999;&quot;&gt;
&lt;span style=&quot;font-size: x-small;&quot;&gt;A: When a server initially fails (for whatever reason: hardware, 
network, software) the application will briefly get errors for any data 
which that server was responsible for. Requests for data on other 
servers will not be impacted. These errors will continue until the node 
is “failed over” which activates the replica data (vbuckets) elsewhere 
in the cluster. The amount of time will vary depending on whether you 
are using automatic or manual failover…&lt;/span&gt;&lt;span style=&quot;background-color: yellow; font-size: x-small;&quot;&gt;but once the failover is 
triggered there is no more delay&lt;/span&gt;&lt;span style=&quot;font-size: x-small;&quot;&gt;. You might ask “but why can’t I read 
from the replica data that already exists.”&amp;nbsp; The answer is two-fold.&amp;nbsp; 
First, we specifically disallow access to the replica data (while it is 
“replica”) to preserve the very strong consistency that our system 
provides. Under normal operation, you are guaranteed to “read your own 
writes” &lt;/span&gt;&lt;span style=&quot;background-color: yellow; font-size: x-small;&quot;&gt;and this is done by only providing one location for accessing 
any given piece of data&lt;/span&gt;&lt;span style=&quot;font-size: x-small;&quot;&gt;. By allowing unrestricted reading of replicas, 
you might have a situation where one client writes a piece of data to 
the active copy and another client immediately tries to read that data 
from the replica…leading to possible inconsistency. Now, the second part
 of this answer is that we are currently working on feature to allow for
 reading from these replicas. It will be a new operation that is 
explicitly invoked by the application so that there won’t be any 
confusion about which copy is being read from. You’ll still want to 
failover the node as quickly as possible since writes will continue to 
fail. This is one example of the many features we have added as a direct
 response to our customers’ and users’ demands…you speak, and we listen 
(and then do something about it too)!&lt;/span&gt;&lt;/div&gt;
О&amp;gt; Когда произошёл сбой на сервере (по любой причине: оборудование, сеть, программа) приложение будет получать ошибки при запросе любых данных с этого сервера. Запрошенные с других серверов данные останутся прежними. Эти ошибки будут идти до узла, который активировал репликацию данных (vbuckets). Продолжительность будет варьироваться в зависимости от использованного режима отказоустойчивости - ручного или автоматического... Вы можете спросить: &quot;Но почему я не могу прочесть данные из реплики, которая уже существует?&quot; Ответ складывается из двух частей. Во-первых, мы специально запретили доступ к реплике, чтобы сохранить строгую согласованность данных в нашей системе. При нормальной работе вам гарантируется возможность &quot;читать собственные данные&quot;. Позволив неограниченное чтение реплик, можно получить ситуацию, когда один клиент записывает часть данных в активную копию, а другой в это же время пытается прочитать данные из реплики... что, возможно, приведёт  к несогласованности. Вторая часть ответа касается возможности чтения из этих реплик. Это должна быть новая операция, в которой приложение ясно говорит, что прочитанные данные не внесут путаницы в работу. Вы до сих пор получаете быстрый отказоустойчивый узел, но запись в него вызовет сбой. Это лишь один пример, как много возможностей мы добавили, выслушав наших заказчиков и пользователей... Вы говорите, мы слушаем (и делаем)!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-size: x-small;&quot;&gt;&lt;span style=&quot;color: #999999;&quot;&gt;Q: Is there any effect/risk/time when rebalancing a system under heavy write loads? Is it best to add nodes during quite times?&lt;/span&gt;&lt;/span&gt; &lt;br /&gt;
&lt;b&gt;В&amp;gt; Действия / риски / время при восстановлении равновесия (перебалансировки) системы при большом частоте записей в неё.&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;div style=&quot;color: #999999;&quot;&gt;
&lt;span style=&quot;font-size: x-small;&quot;&gt;A: By design, the rebalance operation is done asynchronously so as to
 have as minimal-as-possible an impact on the performance of the 
cluster. However, the reality is that rebalancing puts an increased load
 on the cluster and requires resources in order to do so (network, disk,
 RAM, CPU). If the cluster is already close to capacity, any increased 
load may impact the application’s performance. While safe to do at 
anytime, we highly recommend performing your own tests in your own 
environment to characterize what, if any, impact will be had by a 
rebalance. Typically our customers perform these at low or quiet times, 
but the main advantage is that you don’t need to take the application 
completely offline as you continue to scale.&lt;/span&gt;&lt;/div&gt;
О&amp;gt; По замыслу, операция перебалансировки производится асинхронно, так что имеем минимальное влияние на производительность кластера. Однако, в реальности перебалансировка увеличивает нагрузку на кластер и требует ресурсов (сеть, диск, память, процессор). Если кластер уже наполнен до отказа, любая загрузка в него может влиять на производительность приложения. Хотя это безопасно, мы очень рекомендуем провести свои собственные тесты, чтобы определить степень влияния перебалансировки на вашу систему. Обычно наши клиенты уделяют этому вопросу мало времени, но основное преимущество перебалансировки - вам не нужно останавливать работу системы, чтобы ускорить её работу.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;div style=&quot;color: #999999;&quot;&gt;
&lt;span style=&quot;font-size: x-small;&quot;&gt;Q: What’s a vbucket?&lt;/span&gt;&lt;/div&gt;
&lt;b&gt;В&amp;gt; Что такое vbucket?&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;div style=&quot;color: #999999;&quot;&gt;
&lt;span style=&quot;font-size: x-small;&quot;&gt;A: A vbucket is our way of logically partitioning data so that it can
 be spread across all the nodes within a cluster. Every Couchbase-type 
bucket that gets created on the cluster is automatically (and 
transparently) split up into a static set of slices (the vbuckets). 
These are then “mapped” to individual servers. When a node is added or 
removed, it is these slices that get moved around and re-mapped to 
provide linear and non-disruptive scaling. &lt;span style=&quot;background-color: yellow;&quot;&gt;While totally abstracted from
 the application and user, it’s important to realize that vbuckets exist
 “under-the-hood” to provide much of the wonderful capabilities that 
Couchbase Server has&lt;/span&gt;. You can learn more about the vbucket concept here:
 &lt;a href=&quot;http://www.couchbase.org/wiki/display/membase/vBuckets&quot;&gt;http://www.couchbase.org/wiki/display/membase/vBuckets&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;
О&amp;gt; vbucket - это наш вариант логического деления данных, которые могут передаваться между узлами кластера. Каждый пакет (bucket) в кластере автоматически (и прозрачно) разбивает наборы данных на куски (vbucket). Пакеты затем &quot;проецируются&quot; на отдельные серверы. Когда узел добавляется или убирается, части данных перемещаются и перепроецируются. Это происходит без прерывания работы системы. Пакеты не затрагивают приложение и пользователя. Вы можете узнать больше о концепции vbucket здесь &amp;gt; &lt;a href=&quot;http://www.couchbase.org/wiki/display/membase/vBuckets&quot;&gt;http://www.couchbase.org/wiki/display/membase/vBuckets&lt;/a&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;color: #999999;&quot;&gt;Monitoring&lt;/span&gt;&lt;br /&gt;
&lt;b&gt;&lt;span style=&quot;font-size: large;&quot;&gt;Отслеживание&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;span style=&quot;font-size: large;&quot;&gt;&amp;nbsp;&lt;/span&gt;
&lt;br /&gt;
&lt;div style=&quot;color: #999999;&quot;&gt;
&lt;span style=&quot;font-size: x-small;&quot;&gt;Q: Is the Couchbase Server Web UI the only method of monitoring a Couchbase Server cluster?&lt;/span&gt;&lt;/div&gt;
&lt;b&gt;В&amp;gt; Веб-интерфейс Couchbase Server - единственный способ наблюдать за работой кластера?  &lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;div style=&quot;color: #999999;&quot;&gt;
&lt;span style=&quot;font-size: x-small;&quot;&gt;A: Not necessarily, no. All that you see and can do in the Web UI is actually driven by our REST interface (&lt;a href=&quot;http://www.couchbase.org/wiki/display/membase/Membase+Management+REST+API&quot;&gt;http://www.couchbase.org/wiki/display/membase/Membase+Management+REST+API&lt;/a&gt;)
 that is programmatically accessible externally. &amp;nbsp;Additionally, each 
individual server (and each individual bucket on that server) provides 
its own “raw” statistics that are used by the REST API.&amp;nbsp; These raw 
statistics are available externally as well: &lt;a href=&quot;http://www.couchbase.org/wiki/display/membase/Monitoring+Membase&quot;&gt;http://www.couchbase.org/wiki/display/membase/Monitoring+Membase&lt;/a&gt;.&amp;nbsp;
 It is our goal to provide as much information as possible about the 
system so that our users can effectively monitor it both from a capacity
 planning perspective and a diagnostic/troubleshooting perspective when 
things start to go wrong (or to prevent things from going wrong in the 
first place.&lt;/span&gt;&lt;/div&gt;
О&amp;gt; Вовсе нет. Всё, что вы видите и можете делать в веб-интерфейсе Couchbase Server, управляется нашим &lt;a href=&quot;http://www.couchbase.org/wiki/display/membase/Membase+Management+REST+API&quot;&gt;REST-интерфейсом&lt;/a&gt;, доступным внешним программам. Также, каждый конкретный сервер (и каждый конкретный пакет на сервере) предоставляет по REST API собственную &quot;сырую&quot; статистику. Эта сырая статистика также &lt;a href=&quot;http://www.couchbase.org/wiki/display/membase/Monitoring+Membase&quot;&gt;доступна извне&lt;/a&gt;. Наша цель - предоставить информацию о системе так много, насколько возможно, чтобы наши пользователи могли эффективно наблюдать работу кластера, планирую т.о. наращивание мощностей и диагностирую/исправляя проблемы, как только они возникнут (или предупреждать их возниконовение). &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;div style=&quot;color: #999999;&quot;&gt;
&lt;span style=&quot;font-size: x-small;&quot;&gt;Q: What kind of alerting does Couchbase Server provide?&lt;/span&gt;&lt;/div&gt;
&lt;b&gt;В&amp;gt; Какие виды оповещения предоставляет Couchbase Server? &lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;div style=&quot;color: #999999;&quot;&gt;
&lt;span style=&quot;font-size: x-small;&quot;&gt;A: Technically, we are not a company that makes alerting software.&amp;nbsp; 
In our minds, our job is to provide an interface for other systems to 
make use of.&amp;nbsp; Most larger organizations would not want each piece of 
technology in their stack sending out a differently formatted set of 
alerts. That is why we have made it so easy to plug our statistics and 
monitoring data into any other system.&amp;nbsp; However, we also realize that 
some smaller environments may in fact want our software to provide this 
out of the box. &amp;nbsp;We are working on extending our capabilities here and 
already provide alerts for when nodes go down.&lt;/span&gt;&lt;/div&gt;
О&amp;gt; Технически, мы не компания, что создаёт приложения для оповещения. По&amp;nbsp; нашему мнению, наша работа - предоставить интерфейс для других систем. Большинство организаций не хотят собирать по кусочкам оповещения, отправленные в разных форматах. Однако, мы реализуем небольшую среду окружения, которая может использоваться &quot;из коробки&quot; (без необходимости подключения других приложений). Мы работаем над расширением возможностей и уже передаём оповещения об узлах, которые &quot;упали&quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;color: #999999;&quot;&gt;Autocompaction&lt;/span&gt;&lt;br /&gt;
&lt;b&gt;&lt;span style=&quot;font-size: large;&quot;&gt;Автоматическое сжатие&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;span style=&quot;font-size: large;&quot;&gt;&amp;nbsp;&lt;/span&gt;
&lt;br /&gt;
&lt;div style=&quot;color: #999999;&quot;&gt;
&lt;span style=&quot;font-size: x-small;&quot;&gt;Q: If you abort the compaction at the end of the timeperiod, is the 
compaction done up until that point still saved or is all compaction 
done thus far lost?&lt;/span&gt;&lt;/div&gt;
&lt;b&gt;В&amp;gt; Если прервать процесс сжатия базы, последующий запуск сжатия продолжится с сохранённой точки или начнётся сначала? &lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;div style=&quot;color: #999999;&quot;&gt;
&lt;span style=&quot;font-size: x-small;&quot;&gt;A: Normally, a compaction is all-or-nothing and so aborting it will 
lose the progress that has been made so far.&amp;nbsp; However, within Couchbase 
Server, we are performing the compaction on a per-vbucket (see above) 
basis and so the whole dataset can actually be compacted incrementally 
without losing all of the progress it has made when aborted.&lt;/span&gt;&lt;/div&gt;
О&amp;gt; Нормально, когда сжатие проходит по принципу &quot;всё или ничего&quot; и прерывание сжатия приводит к необходимости начать его сначала. Однако, с Couchbase 
Server мы выполняем сжатие по пакетам (vbucket, см. выше) и целый набор данных в действительности сжимается инкрементно, без потери прогресса в случае отмены сжатия. &amp;nbsp; &amp;nbsp; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;color: #999999;&quot;&gt;Autofailover&lt;/span&gt;&lt;br /&gt;
&lt;b&gt;&lt;span style=&quot;font-size: large;&quot;&gt;Автоматическая отказоустойчивость&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;span style=&quot;font-size: large;&quot;&gt;&amp;nbsp;&lt;/span&gt;
&lt;br /&gt;
&lt;div style=&quot;color: #999999;&quot;&gt;
&lt;span style=&quot;font-size: x-small;&quot;&gt;Q: Why is a delay imposed before the cluster will automatically failover a downed node?&lt;/span&gt;&lt;/div&gt;
&lt;b&gt;В&amp;gt; Почему введена задержка до того как кластер автоматически отключит упавший узел? &lt;/b&gt;&amp;nbsp; &lt;br /&gt;
&lt;br /&gt;
&lt;div style=&quot;color: #999999;&quot;&gt;
&lt;span style=&quot;font-size: x-small;&quot;&gt;A: By default, the software is configured with a 30-second minimum before automatic failover will kick in.&amp;nbsp; &lt;/span&gt;&lt;span style=&quot;font-size: x-small;&quot;&gt;This is designed to prevent the software from doing the “wrong thing”.&lt;/span&gt;&lt;span style=&quot;font-size: x-small;&quot;&gt;&amp;nbsp; &lt;/span&gt;&lt;span style=&quot;font-size: x-small;&quot;&gt;For
 example, if a node is simply slow to respond, or there is a brief 
network hiccup, you wouldn’t want it to be failed over and so the 
cluster will wait to ensure that the node is actually down.&lt;/span&gt;&lt;span style=&quot;font-size: x-small;&quot;&gt;&amp;nbsp;&amp;nbsp;
 There are a few other situations to be taken into consideration and you
 can read more about these and our design decisions to handle them &lt;a href=&quot;http://www.couchbase.org/wiki/display/membase/Failover+Best+Practices&quot;&gt;here&lt;/a&gt;.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;
&lt;span style=&quot;font-size: 17px;&quot;&gt;О&amp;gt; По умолчанию, приложение сконфигурировано с 30-секундным минимум до автоматического исправления проблемы. Это защищает приложение от &quot;неправильного поведения&quot;. Например, если узел просто медленно отвечает или в сети небольшой сбой, вы не хотите получить сигнал об ошибке и поэтому кластер будет ждать, чтобы быть уверенным, что узел действительно упал. Существует и несколько других ситуаций, достойных рассмотрения и вы можете прочитать больше о них и о наших проектных решения &lt;a href=&quot;http://www.couchbase.org/wiki/display/membase/Failover+Best+Practices&quot;&gt;здесь&lt;/a&gt;. &amp;nbsp; &lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-size: 17px;&quot;&gt; &lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;div style=&quot;color: #999999;&quot;&gt;
&lt;span style=&quot;font-size: x-small;&quot;&gt;To get even more information, you can view the 25-30 minute videos of each week&#39;s webinar by going &lt;a href=&quot;http://www.couchbase.com/on-demand/webinar/couchbase-server-2.0-overview&quot;&gt;here&lt;/a&gt;. And the authoritative place for all information regarding Couchbase Server 2.0 can be found &lt;a href=&quot;http://www.couchbase.org/get/couchbase/2.0.0&quot;&gt;here&lt;/a&gt;. While
 this series may have come to a conclusion, we are already planning on 
starting up another one to highlight not only the features of Couchbase 
Server 2.0, but also Couchbase Mobile, our SDKs/client libraries and 
more! Some of the topics will include:&lt;/span&gt;&lt;/div&gt;
&lt;ul style=&quot;color: #999999;&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-size: x-small;&quot;&gt;Cross-cluster synchronization (aka cross-data center replication)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-size: x-small;&quot;&gt;Backup/Restore with Couchbase Server 2.0&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-size: x-small;&quot;&gt;Upgrading from Membase 1.7&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-size: x-small;&quot;&gt;And more!&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
Чтобы получить больше информации, вы можете посмотреть &lt;a href=&quot;http://www.couchbase.com/on-demand/webinar/couchbase-server-2.0-overview&quot;&gt;25-30-минутное видео&lt;/a&gt; каждой недели вебинара. Авторитетный источником информации о Couchbase Server 2.0 - &lt;a href=&quot;http://www.couchbase.org/get/couchbase/2.0.0&quot;&gt;здесь&lt;/a&gt;. Хотя эта серия вебинаров завершилась, мы уже планируем начать следующую, осветив не только возможности Couchbase 
Server 2.0, но также Couchbase Mobile, наши SDK, клиентские библиотеки и многое другое! Вот некоторые темы:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Синхронизация кластеров (ака репликация между дата-центрами)&lt;/li&gt;
&lt;li&gt;Резервное копирование / восстановление с помощью Couchbase Server 2.0&lt;/li&gt;
&lt;li&gt;Обновление Membase 1.7&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;div style=&quot;color: #999999;&quot;&gt;
&lt;span style=&quot;font-size: x-small;&quot;&gt;To make it even better, I&#39;m asking you to help participate! Please comment here (or send me an email directly at &lt;a href=&quot;mailto:perry@couchbase.com&quot;&gt;perry@couchbase.com&lt;/a&gt;) with any topics that think we need to cover more and we’ll do our best to include them in an upcoming webinar.&lt;/span&gt;&lt;/div&gt;
Чтобы сделать это лучше, я прошу вас помочь своим участием! Пожалуйста, комментируйте &lt;a href=&quot;http://blog.couchbase.com/couchbase-server-20-most-common-questions-and-answers&quot;&gt;здесь&lt;/a&gt; (или отправьте email на &lt;a href=&quot;mailto:perry@couchbase.com&quot;&gt;perry@couchbase.com&lt;/a&gt;) с любой темой, которую, думаете, надо раскрыть больше - и мы сделаем всё возможное, чтобы включить их в предстоящий вебинар.</content><link rel='replies' type='application/atom+xml' href='http://signmotion.blogspot.com/feeds/4882752969078204948/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2909062909816541374/4882752969078204948?isPopup=true' title='Комментарии: 1'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2909062909816541374/posts/default/4882752969078204948'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2909062909816541374/posts/default/4882752969078204948'/><link rel='alternate' type='text/html' href='http://signmotion.blogspot.com/2011/10/couchbase-server-20.html' title='Couchbase Server 2.0 &gt; Общие вопросы и ответы (по итогам вебинара)'/><author><name>Andrii</name><uri>http://www.blogger.com/profile/02715216472597824596</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjcrHHkyfsW8m8HmZZeyd2fhzwEl-shXbCxnYVY_mVq7uJpe5QET9SerP_bCPeO4YEBlXJT44IRPOcL7VtgFJsDqXwfppdES-fdokbXX0-11jdBQAyipvURKBH3N-Wh2VCye2U-W4nsp6zPgNSyi7g6gFgmmo34dH_oL_FTXf31U65BXQ/s220/Andrey-400x.png'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0-_ka-Rj7u8DWhj5E66BvdRMEATl5pyrJ12eTesjgDx7mTfYdt4c4_PxXsRCDdjp5lMy186ft2rocfuokkG5cypgU1s7QqbOHVHkk8BAGTwvfGhuGXnBJfJXogFhPrbAiVAnkHwwLNfhM/s72-c/couchbase-server-2.png" height="72" width="72"/><thr:total>1</thr:total></entry></feed>