--- title: Точка масштабирования круга | After Effects description: Как найти Anhor Point круга, изменяя Scale из которого, он полностью совпадет с другим кругом? image: https://i.imgur.com/MVSvCuN.png previewImageSize: large --- <style> /* img{ border: solid black; } */ img[loading]:not([src$='#default']){ display: block; margin: auto; } img[loading]:not([src$='#default']):not([width]){ width: 50%; } .markdown-body h1{ border-bottom: unset; } hr.dots{ all: unset; display: block; font-family: 'Rubik'; text-align: center; font-size: 6px; letter-spacing: 20px; line-height: 60px } hr.dots:after{ content: '■■■' } img[id]{ display:none; } </style> TG: [@antsharrr](https://t.me/antsharrr) # AE tips | поиск центра окружности ## Предисловие Задача, конечно, интересная и если не знать математики, решить ее можно лишь "методом тыка", что, собственно, от части и было сделано. Такой вот эмпирический подход дает возможность самому стать на место первооткрывателей геометрических фактов, что также полезно, я считаю. Однако, я здесь хотел бы обсудить эту же задачу, но подойдя к ней изначально с математической точки зрения, используя ранее полученные результаты древних. Забегая вперед, сразу отмечу, что при таком расположении окружностей, **не существует** такой такой точки плоскости, масштабируя из которой одну окружность, она полностью перейдет во вторую. Почему это так, разберемся чуть позже, а пока перейдем к решению в общем виде. ![](https://codimd.s3.shivering-isles.com/demo/uploads/02a6da1fb9d19367162f42367.png#default) Забавно получается на фоне того, что именно это стало причиной возникновения данной задачи. <hr class=dots> ## Ход решения Начнем, на первый взгляд, с чего-то, совершенно не имеющего отношения к нашей задаче, но позднее окажется непосредственно связанным с конструкцией окружностей. <!-- Начнем не совсем с окружностей, но с того, что окажется тесно связанным с ними — биссектрисой угла. --> Итак, думаю, все себе представляют, что такое угол, но важно, чтобы мы говорили об одном и том же, поэтому дам строгое определение > **Определение.** *Углом* называется фигура, образованная двумя лучами, выходящими из одной точки <!-- <div style="height:60px"></div> --> ![](https://codimd.s3.shivering-isles.com/demo/uploads/02a6da1fb9d19367162f42386.png) То есть, угол изначально не имеет ничего общего с *градусами*, что является частым заблуждением. Градусы — лишь единица измерения — числовая характеристика, позволяющая как-то количественно сравнивать углы между собой. > **Определение.** *Биссектрисой* угла называется луч, выходящий из его вершины и делящий данный угол пополам ![](https://codimd.s3.shivering-isles.com/demo/uploads/02a6da1fb9d19367162f42387.png) Биссектриса обладает таким свойством, что проведя из любой точки на ней перпендикуляры к лучам угла, то они будут равны ![](https://codimd.s3.shivering-isles.com/demo/uploads/02a6da1fb9d19367162f42388.png) Доказывается это утверждение по теореме о подобии треугольников $\Delta OAC$ и $\Delta OBC$ по двум глам: $\angle OAC = \angle OBC = 90^\circ$ — по построению перпендикуляров, $\angle AOC = \angle BOC$ по определению биссектрисы. А поскольку сторона $OC$ является общей для данных двух треугольников, то они равны, а значит и все стороны у них равны. И тут впервые появляются окружности, которые, кстати, представляют из себя > **Определение.** *Окружностью* называется геометрическое место точек, равно удаленных от заданной точки — центра окружности. ![](https://codimd.s3.shivering-isles.com/demo/uploads/02a6da1fb9d19367162f42389.png) Все отрезки, соединяющие любую точку отрезка и ее центра, называемые *радиусами*, равны. <div style="height:10px"></div> Теперь вернемся на один рисунок назад, к нашей конструкции. Через точки $A$ и $B$ можем провести окружность с центром $C$, причем сделать это можно единственным образом и тогда лучи угла буду касательными к проведенной окружности. Действительно, так как наикротчайшее расстояние от точки $C$ к лучу $OA$ (аналогично $OB$ ) — это перпендикуляр (который и называется *расстоянием* от точки к прямой), то все остальные отрезки, соединяющие точку $C$ с любой другой точкой луча будут длиннее радиуса, следовательно $A$ и $B$ — таки точки касания и ни в каких других точках окружность не пересекается с углом. Единственность построения окружности через эти точки нетрудно доказать от противного. ![](https://codimd.s3.shivering-isles.com/demo/uploads/02a6da1fb9d19367162f4238a.png) <i id="similar-triangles"></i> А далее ключевой момент в понимании решения. Рассмотрим два теугольника $\Delta OAC$ и $\Delta OA_1C_1$. По теореме о подобии треугольников, так как $\angle AOC=\angle A_1OC_1$ и $\angle OAC = \angle OA_1C_1\; (= 90^\circ)$, то существует $k$ — коэффициент пропорциональности. <img style="display:inline" src="https://codimd.s3.shivering-isles.com/demo/uploads/02a6da1fb9d19367162f4238b.png" loading="lazy"> <img style="display:inline" src="https://codimd.s3.shivering-isles.com/demo/uploads/02a6da1fb9d19367162f4238c.png" loading="lazy"> Подобие треугольников означает, что отмасшабировав один треугольник в $k$ раз, их можно полностью совместить со вторым. Нетрудно заметить, что в данном случае, треугольники можно совместить без их дополнительного перемещения: достаточно выполнить масштабирование из точки $O$, которая является общей для обоих треугольников. <div style="height:30px"></div> > [color=#F6455A] <p style="color:black">А теперь, внимание! Точка $C$ — центр окружности, что была показана ранее, а отрезок $CA$ — ее радиус. Так как увеличение треугольника в $k$ раз значит увеличение каждой его стороны в $k$ раз, то $O$ — такая точка, что увеличивая из нее, отрезки $OC$ и $CA$ будут линейно и равномерно увеличиваться, то есть увеличение окружности будет происходить в равной мере с перемещением ее по биссектрисе.</p> <div style="height:70px"></div> ![](https://i.imgur.com/i5GkF6t.gif) Таким образом, искомый annchor point — вершина угла, в который вписаны обе окнужности. Завершая теоретический разговор, хочется лишь отметить, что такая конструкция является необходимым и достаточным условием существования точки, масштабируя из которой, одна окружность перейдет в другую. > **Доказательство.** Достаточность очевидна, поскольку мы начали с того, что взяли конкретную точку (вершину угла) и для нее показали такое свойство. > > Остается понять только про то, что для любых двух заданных окружностей, если к ним можно провести две общие внешние касательные, тогда точка пересечения этих касательных и будет тем самым anchor point. > На самом деле, это скрывается в рассуждениях выше, когда вводилась связь между биссектрисой и расстояниями к лучам угла. > > Пусть мы нашли две общие внешние касательные, пересекающиеся в точке $O$, тогда, в частности, это касательные и к какой-то одной из них. Вспоминая определение окружности, понимаем, что проведя отрезки в точки касания, они будут равны как радиусы, а тогда по теореме о подобных треугольника, в этот раз поскольку равны стороны: катеты ($AC = BC$) и общая гипотенуза ($OC$), по эти треугольники равны. Это значит, что и соответствующие углы у них равны. В частности, $\angle AOC = \angle BOC$, ну а тогда прямая $OC$ — биссектриса. > ![](https://codimd.s3.shivering-isles.com/demo/uploads/02a6da1fb9d19367162f42399.png) <br> Из этого взаимно однозначного соответствия и следует упомянутое в начале утверждение: если одна окружность полностью лежит в другой, тогда не существует общих касательных к ним, поэтому и искомого anchor point также не существует по доказанному ранее. Хочется отметить еще один вырожденный случай, когда окружность в точности раны по размеру. В этом случае существуют общие внешние касательные, однако они параллельны, то есть не пересекаются, так что в этом случае также не найдется anchor point. ![](https://codimd.s3.shivering-isles.com/demo/uploads/02a6da1fb9d19367162f423a2.png) > [color=#B6C6A4] <p style="color:black"> Наконец, хочется только отметить, что если бы задача стояла найти точку, масштабируя из которой, центр одной окружности совпал с другой, то это **всегда** можно сделать, независимо от размера и расположения окружностей. Более того, для выбранной окружности, которая будет масштабироваться и смещаться, беря абсолютно произвольную точку, за исключением центра выбранной окружности, на прямой, проходящей через центр обоих окружностей, всегда найдется такой коэффициент пропрорциональности $k$, который совместит центры. ![](https://i.imgur.com/DYbykNl.gif =500x) </p> <br> <hr class=dots> ## Вычисление решения Нам известны координаты центров окружностей: $C$ и $C_1$, а также их радиусы, которые обозначим как-нибудь для дальнейших вычислений $$ r_1 = |AC|, \quad r_2 = |A_1C_1| $$ а также обозначим расстояние между центрами окружностей $$ d = |CC_1| $$ ![](https://codimd.s3.shivering-isles.com/demo/uploads/8f7ada9e0ecffe4bf44d6eb69.png) Можно сказать, что мы имеем полную информацию о биссектрисе, ведь через две точки (центры окружностей, в нашем случае) проходит единственная прямая. Поэтому, по сути, найдя достаточно информации об одной из касательной, этого будет хватит для нахождения координат $O$, так как эта точка будет точкой пересечения касательной и биссектрисы. Поскольку мы теперь имеем дело с координатами, нужно ввести координатные оси. Для начала будем считать, что ось $Ox$ проходит как раз через нашу биссектрису. ![](https://codimd.s3.shivering-isles.com/demo/uploads/8f7ada9e0ecffe4bf44d6eb6c.png) Из рассуждений [выше](#similar-triangles), мы поняли, что треугольники $\Delta OAC$ и $\Delta OA_1C_1$ — подобны, поэтому существует такое число $k$, что <i id=similar-ratio></i> $$ \begin{cases} |OA_1|=k\cdot|OA| \\ |OC_1| = k\cdot|OC| \\ |A_1C_1|=k\cdot|AC| \end{cases} \quad\Rightarrow\quad \frac{|OA_1|}{|OA|}=k,\enspace \frac{|OC_1|}{|OC|}=k,\enspace \frac{|A_1C_1|}{|AC|}=k $$ в частности $$ \frac{|OC_1|}{|OC|}=k=\frac{|A_1C_1|}{|AC|} $$ Заметим, что $|OC_1| = |OC|+|CC_1|$ и вспоминая введенные обозначения, получим <i id=distance-to-O></i> $$ \begin{array}{} &\dfrac{|OC|+d}{|OC|} = \dfrac{r_2}{r_1} &\Leftrightarrow& \color{gray}{\dfrac{|OC|}{|OC|}+\dfrac{d}{|OC|} = \dfrac{r_2}{r_1}} &\color{gray}\Leftrightarrow& \color{gray}{\dfrac{d}{|OC|} = \dfrac{r_2}{r_1}-1} &\color{gray}\Leftrightarrow\\ \color{gray}\Leftrightarrow& \color{gray}{\dfrac{d}{|OC|} = \dfrac{r_2}{r_1}-\dfrac{r_1}{r_1}} &\color{gray}\Leftrightarrow& \color{gray}{\dfrac{d}{|OC|} = \dfrac{r_2-r_1}{r_1}} &\Leftrightarrow& |OC| = d\cdot\dfrac{r_1}{r_2-r_1} & \quad(*)\hspace{-5ex} \end{array} $$ Таким образом, мы нашли длину $|OC|$ и сместившись на это расстояние от центра окружности $C$, мы найдем координаты $O$. Может показаться, что касательную прямую мы вовсе не задействовали, однако $|OC|$ был найден именно из предположения о том, что существует касательная с точками касания $A$ и $A_1$ и именно из этого предположения мы установили подобие треугольников и, собственно, нашли $|OC|$. Конечно, можно было бы явно найти координаты точек касания $A$ и $A_1$, написать уравнения биссектрисы и касательной, как прямых проходящих через две точки <i id=line-equation></i> $$ \frac{y-y_1}{y_2-y_1} = \frac{x-x_1}{x_2-x_1} \quad\Leftrightarrow\quad y = \frac{y_2-y_1}{x_2-x_1}(x-x_1)+y_1 \hspace{15ex}(**)\hspace{-15ex} $$ затем отыскать аналитически точку пересечения. Но согласитесь, это куда трудозатратнее, чем представленный способ. <br> Поскольку изначально, для простоты, мы положили координатную ось на биссектрису, то теперь необходимо учесть произвольное положение конструкции угла с вписанными окружностями. ![](https://codimd.s3.shivering-isles.com/demo/uploads/8f7ada9e0ecffe4bf44d6eb90.png) Пусть $\varphi$ — угол между биссектрисой и координатной осью $Ox$. Обозначим координаты центра как $C = (C_x,C_y)$, тогда, чтобы из точки $C$ попасть в $O$, необходимо к $x$-координате $C$ прибавлять не $|OC|$, а ее проекцию — $|O'C'|$, которая просто вычисляется $$ |O'C'| = |OC|\cos\varphi $$ тогда из формулы [$(*)$](#distance-to-O) получим $$ |O'C'| = |OC|\cos\varphi = d\cdot\dfrac{r_1}{r_2-r_1}\cdot\cos\varphi = d\cos\varphi\cdot\dfrac{r_1}{r_2-r_1} = |C'C'_1|\cdot\dfrac{r_1}{r_2-r_1} $$ Последнее равенство следует из того, что мы положили $d=|CC_1|$, а умножая на косинус угла наклона прямой, мы получим ничто иное, как проекцию на $Ox$, то есть $|C'C'_1|$. Теперь встает вопрос, как найти $|C'C'_1|$. Да очень просто! Мы ведь знаем координаты центров окружностей $C=(C_x,C_y)$ и $C_1=(C_{1y},C_{1x})$, но тогда $$ |C'C'_1| = C_x - C_{1x} $$ Поэтому, если изначально взять в качестве $d$ — разность $x$-координат центров, тогда по сравнению с формулой для первого случая, ничего не изменится. <i id="point-on-line"></i> Итак, мы теперь знаем $x$-координату точки $O=(O_x,O_y)$, которая вычисляется как $$ O_x = C_x + d\cdot\frac{r_1}{r_2-r_1} $$ А для нахождения $y$-координаты, наиболее простым способом будет воспользоваться тем, что $O$ лежит на биссектрисе. Так как если $y=f(x)$ — уравнение прямой-биссектрисы, при значении аргумента $O_x$, получим $f(O_x)=O_y$. По формуле [$(**)$](#line-equation), находим уравнение биссектрисы, проходящая через $C$ и $C_1$ $$ y = f(x) = \frac{C_{1y}-C_y}{C_{2y}-C_y}(x-C_x)+C_y $$ <br> <hr class=dots> <br> Прежде, чем перейти к реализации этих вычислений в коде, хотелось сделать замечание по поводу того, почему [представленный](https://medium.com/@ae_tips/67a321b5c769#ed76) способ также работает. ## Альтернативное решение Как и раньше, проведем прямую, проходящую через центры окружностей (как мы уже знаем, это будет биссектриса некоторого угла с вершиной $O$). И теперь возьмем произвольную точку на окружности $D$ и проведем радиус к ней, после чего проведем радиус второй окружности под таким же углом биссектрисе, что и первый радиус. Тогда радиусы $CD$ и $C_1D_1$ будут параллельны. ![](https://codimd.s3.shivering-isles.com/demo/uploads/8f7ada9e0ecffe4bf44d6ebad.png) Проведем через точки $D$ и $D_1$ прямую. Она пересечет биссектрису в некоторой точки $\widetilde O$. Мы пока не знаем, что это за точка, поэтому рассмотрим треугольники $\Delta \widetilde ODC$ и $\Delta \widetilde OD_1C_1$. Они подобны по двум углам: $\angle \widetilde OCD = \angle \widetilde OC_1D_1$ и $\angle \widetilde ODC = \angle \widetilde OD_1C_1$ по построению. А тогда, по абсолютно алогичным рассуждениям [выше](#similar-ratio), получаем, что $$ \begin{gather} \frac{|\widetilde OC_1|}{|\widetilde OC|}=\frac{|D_1C_1|}{|DC|}, \quad |D_1C_1| = r_2, \enspace |DC| = r_1, \\ |\widetilde OC_1| = |\widetilde OC| + |CC_1| = |\widetilde OC| + d, \\[1ex] \frac{|\widetilde OC|+d}{|\widetilde OC|}=\frac{r_2}{r_1} \end{gather} $$ но, с другой стороны, до этого, мы [нашли](#distance-to-O), что $$ \frac{|OC|+d}{|OC|}=\frac{r_2}{r_1} $$ Отсюда получаем, что $$ \frac{|\widetilde OC|+d}{|\widetilde OC|}=\frac{r_2}{r_1}=\frac{|OC|+d}{|OC|} \quad\Rightarrow\quad |\widetilde OC| = |OC| \quad\Rightarrow\quad \widetilde O = O $$ ![](https://codimd.s3.shivering-isles.com/demo/uploads/8f7ada9e0ecffe4bf44d6ebae.png) А поскольку точка $D$ (как и $D_1$) была выбрана произвольно на окружности, получаем справедливость утверждения для всех точек. ![](https://i.imgur.com/dSEDQFW.gif =500x) Это и доказывает, почему [представленный](https://medium.com/@ae_tips/67a321b5c769#ed76) подход дает также верный результат. <hr class=dots> ## Реализация решения В этом разделе мы также напишем скрипт, который будет находить ту самую точку $O$. Самое главное — большая идея, которая была в [первом разделе](#Ход-решения). Поняв ее, дальше не составит труда выполнить всю арифметику при помощи javascript. Сперва создадим наипростейшую панельку с кнопкой, на клик по которой привяжем выполнение функции, которая и будет находить и перемещать anchor point. ```javascript= function moveAnchor(){ ``` <div style="margin-bottom:-30px"></div> ``` ... ``` <div style="margin-bottom:-30px"></div> ```javascript=31 } var scriptWindow = new Window("palette{margins: 20}", "Find anchor"); var findButton = scriptWindow.add("button", undefined, "Find"); findButton.onClick = function(){moveAnchor()}; scriptWindow.show() ``` А теперь к главному — описанию функции `moveAnchor`. Обвернем все содержимое в один блок, чтобы все действия функции можно было бы отменить одним действием Undo (Ctrl+Z) ```javascript=2 app.beginUndoGroup("Move anchor to scale-match circles"); ``` <div style="margin-bottom:-30px"></div> ``` ... ``` <div style="margin-bottom:-30px"></div> ```javascript=30 app.endUndoGroup(); ``` Затем в переменную запишем все выделенные слои и выполним проверку, чтобы их было ровно 2. В ином случае прерывать исполнение функции. ```javascript=3 var selLayers = app.project.activeItem.selectedLayers; if(selLayers.length != 2) return; ``` Получим время плейхеда, которое понадобиться позже, лишь в одном техническом месте. ```javascript=6 var curTime = selLayers[0].containingComp.time; ``` Введем переменные для двух выбранных слоев и далее будем производить вычисления для anchor point первого выбранного слоя. ```javascript=8 var circle1 = selLayers[0]; var circle2 = selLayers[1]; ``` Чтобы получить реальный размер слоев, используется метод `sourceRectAtTime`, который принимает два аргумента, первый из которых, как раз таки время. Для этого нам и нужна была ране объявленная переменная `curTime`. Вообще говоря, если слои расположены в самом начале таймлайна, то можно было просто передать начальное значение времени — 0 и не определять `curTime`. ```javascript=18 var r1 = circle1.sourceRectAtTime(curTime, false).height/2 * factor1; var r2 = circle2.sourceRectAtTime(curTime, false).height/2 * factor2; ``` Так как круг — симметрическая фигура, то взяв половину высоты слоя, мы получим его радиус. Внимательный читатель должен был заметить переменные `factor1` и `factor2`, которые не были описаны ранее. Так вот дело в том, что даже используя `sourceRectAtTime`, на него не влияет свойство scale слоя, поэтому необходимо домножить еще на ```javascript=12 var factor1 = circle1.scale.value[1]/100; var factor2 = circle2.scale.value[1]/100; ``` Теперь найдем координаты центров окружностей. Это, пожалуй, единственный тонкий момент во всем коде. Все потому, что anchor point и position слоя связаны специальным образом: когда `Anchor Point = [0, 0]`, то мы видим якорную точку в центре круга, а `Position` задает именно ее координаты, поэтому независимо от начального положения anchor point, для получения координат центра, просто вычитаем одно из другого ```javascript=15 var c1 = circle1.position.value - circle1.anchorPoint.value * factor1; var c2 = circle2.position.value - circle2.anchorPoint.value * factor2; ``` Ну и тут мы видим те самые коэффициенты `factor1` и `factor2`. Мы вынуждены домножать координаты anchor point на процентное значение масштабирования слоя, поскольку пространство слоя, в котором находится anchor point — отдельное координатное пространство, не совпадающее с координатами самой композиции и поэтому свойство scale там не учитывается и мы это указываем непосредственно. Эта тема заслуживает отдельной большой статьи, вместе с методами преобразования координат `toComp`, `fromComp`, `toCompVec` и прочими. А пока перейдем дальше к коду, где все последующее возникновения `factor1` и `factor2` имеют аналогичную причину. Назовем расстояние между $x$-координатами центров, как и в наших вычислениях из [второго раздела](#Вычисление-решения). ```javascript=17 var d = (c1-c2)[0]; ``` А вот для $|OC|$ введем более простое название ```javascript=20 var q = d*r1/(r2-r1); ``` Координаты точки $O$ — массив, который определим как `origin`. ```javascript=22 var origin = []; origin[0] = q/factor1; origin[1] = (c1-c2)[1]/(c1-c2)[0] * origin[0]; ``` Здесь `origin[0]` это $O_x$, а `origin[1]` — $O_y$. И $y$-координату мы вычисляем, через $x$-координату. Повторимся, что это связано с тем, что уравнение прямой — функция, принимающая аргумент $x$ и возвращаяющая значение $y$, что было описано [выше](#point-on-line). Как и говорилось ранее, для реального смещения anchor point, нужно компенсировать сдвиг и в позиции, поэтому имеем следующее ```javascript=26 circle1.anchorPoint.setValue(origin); circle1.position.setValue(c1 + origin*factor1); ``` Вот, собственно и все. После применения скрипта, при значении scale первого круга, равное значению scale второго, фигуры полностью совпадут. <div style="width:100%;height:0px;position:relative;padding-bottom:93.628%;"><iframe src="https://streamable.com/e/0yvqp5?loop=0" frameborder="0" width="100%" height="100%" allowfullscreen style="width:100%;height:100%;position:absolute;left:0px;top:0px;overflow:hidden;"></iframe></div> <div style="height:20px"></div> Чуть больше десятка строчек чистого кода, которые решают задачу для любого расположения окружностей относительно друг друга, без ненужных проверок. А все потому, что был выбран научный подход к решению — начиная с теории, продолжая аналитическими вычислениями и только потом заканчивая написанием кода. :::spoiler <span style="font-size:18px;line-height:60px">**Посмотреть код целиком**</span> ```javascript= function moveAnchor(){ app.beginUndoGroup("Move anchor to scale-match circles"); var selLayers = app.project.activeItem.selectedLayers; if(selLayers.length != 2) return; var curTime = selLayers[0].containingComp.time; var circle1 = selLayers[0]; var circle2 = selLayers[1]; var factor1 = circle1.scale.value[1]/100; var factor2 = circle2.scale.value[1]/100; var c1 = circle1.position.value - circle1.anchorPoint.value * factor1; var c2 = circle2.position.value - circle2.anchorPoint.value * factor2; var d = (c1-c2)[0]; var r1 = circle1.sourceRectAtTime(curTime, false).height/2 * factor1; var r2 = circle2.sourceRectAtTime(curTime, false).height/2 * factor2; var q = r1*d/(r2-r1); var origin = []; origin[0] = q/factor1; origin[1] = (c1-c2)[1]/(c1-c2)[0] * origin[0]; circle1.anchorPoint.setValue(origin); circle1.position.setValue(c1 + origin*factor1); app.endUndoGroup(); } var scriptWindow = new Window("palette{margins: 20}", "Find anchor"); var findButton = scriptWindow.add("button", undefined, "Find"); findButton.onClick = function(){moveAnchor()}; scriptWindow.show() ``` ::: Скачать скрипт: [AS_FindAnchorToMatchCircles.jsx](https://files.fm/down.php?i=d4jdagbd9) <hr class=dots> Поскольку кроме простой арифметики, скрипт ничего не делает, то можно было обойтись и экспрешнами, где в качестве нужного расположения будет выступать еще один, в данном случае круг. Это позволяет в реальном времени наблюдать, где должен оказаться anchor point, чтобы совместить два круга. <div style="width:100%;height:0px;position:relative;padding-bottom:93.628%;"><iframe src="https://streamable.com/e/yoej56?loop=0" frameborder="0" width="100%" height="100%" allowfullscreen style="width:100%;height:100%;position:absolute;left:0px;top:0px;overflow:hidden;"></iframe></div> <div style="height:20px"></div> И, по большому счету, код остается идентичным :::spoiler <span style="font-size:18px;line-height:10px">**Посмотреть код целиком**</span> ```javascript= circle1 = thisComp.layer("Circle purple"); circle2 = thisComp.layer("Circle orange"); factor1 = circle1.scale[1]/100; factor2 = circle2.scale[1]/100; c1 = circle1.position - circle1.anchorPoint * factor1; c2 = circle2.position - circle2.anchorPoint * factor2; r1 = circle1.sourceRectAtTime().height/2 * factor1; r2 = circle2.sourceRectAtTime().height/2 * factor2; d = (c1-c2)[0]; q = d*r1/(r2-r1); origin = [] origin[0] = q/factor1; origin[1] = (c1-c2)[1]/(c1-c2)[0] * origin[0]; c1 + origin*factor1; ``` ::: <div style="height:30px"></div> Напоследок хочеться отметить, что любую фигуру можно представить помещенной в окружность, поэтому лишь заменив круги из предыдущего примера на другую фигуру, все по-прежнему будет работать, как и задумано. <div style="width:100%;height:0px;position:relative;padding-bottom:93.628%;"><iframe src="https://streamable.com/e/ihj28x?loop=0" frameborder="0" width="100%" height="100%" allowfullscreen style="width:100%;height:100%;position:absolute;left:0px;top:0px;overflow:hidden;"></iframe></div> <div style="height:20px"></div> Скачать проект: [Find_anchor_to_match_circles_(CC (13)).aep](https://files.fm/down.php?i=mfe9hvqjj) <hr class=dots> <br> Спасибо за внимание! Если остались какие-то вопросы, можете задать мне их в телеграм.