Aug 2, 2009

tree (3)

Alex sent me a modified version of my script. He only did a minor modification, but it brought a totally different and beautiful result.

Here's the script.
I'll think about how to improve this by adding interface, leaves, and so on.


download: b_aics_script_tree_example_edit_090730.zip

Jul 25, 2009

tree (2)

I modified the script of previous article to create “top view” with it. Is it just like this? ... This isn't so beautiful.
Maybe it is better to create more simple, pictogram-like shape rather than persist on reality.

And it needs leaves. it makes needlessly complex image to draw each leaves. But Pathfinder is not available in AI's scripting function.
If Scriptographer's Pathfinder function works well, it may be better to use it.

Jul 24, 2009

tree (1)

Recently I had a suggestion about a script that draws trees of top view for architect use, by an e-mail. This image was made by an experimental script for this. This is an all-too-common fractal shape but implements a bezier curve feature. At least it needs an interface that enables to adjust variables easily, and an implementation of randomness.

download - b_aics_script_tree_example_090724.zip

BTW, Sg for CS4 was released! I haven't tried it yet.

Jul 5, 2009

image: Buildings

This is an image with rot3d.js effect.
I wrote a supplementary small script to randomize the heights of the buildings.

Jun 30, 2009

Sg: rot3d Updated - 06.30

Though there's few response over there, I like tweaking this script (rot3d.js) and uploaded modified version to www.scriptographer.com again.

In this version, it has "fix-z-order" checkbox in the palette. If this option is checked, this script changes the z-order of the objects according to the z-axis value of the center of the each object. Please note that it doesn't always work properly, and this process may destruct the groups.

Another script "rot3d_m.js" that I uploaded yesterday doesn't have this feature.

Jun 28, 2009

Sg: rot3d Updated

I've uploaded another edition of rot3d.js to www.scriptographer.com (as an attachment file to the comment). There's no new feature but some modification of the inside process.

Jun 24, 2009

image: Random Tile




This is the initial state of the above image -- paved hexagonal shapes. As you can imagine, simply randomizing every point creates just messy image. The overlapping points must keep its condition even after randomizing. This script uses an associative array to do this.

download: b_aics_script_random_tile_example.zip

Jun 21, 2009

image: Spiral Sphere


This script creates 2 groups of pathes -- front and back side -- and a circle as an outline.

The sphere's center is the origin of the artboard -- (x, y, z) = (0, 0, 0). And the viewing point is (x, y, z) = (0, 0, infinity). This means the virtual eye is not looking down the sphere. Rather the sphere is leaning toward the eye.

This assumption makes it so simple to check the current point is at the front or back side. It is just to check if the z-axis value is greater than zero or not.

download: b_aics_script_spiral_sphere.zip

Jun 19, 2009

Fixing Sequential Numbers

The code at the end of this article is a simplified example of script for Illustrator CSx that fixes sequential numbers.


"Simplified" means that this script supposes:
  1. There is a opened document.
  2. There're 2 or more objects in the selection of the active document.
  3. All the objects in the selection are text objects.
  4. The contents of the first and last objects are numbers.
If there is something out of these conditions, the script just stops with an error dialog.
But it is preferable to add some codes for checking the conditions and showing more comprehensible dialogs for general users who aren't familiar with JavaScript on errors.
// fixes sequential numbers
var sel = activeDocument.selection;
var num_to = sel[0].contents - 0;
var num_from = sel[ sel.length - 1 ].contents - 0;

var unit = (num_to - num_from) / (sel.length - 1);

var digit = 0;
if( sel[0].contents.match(/\.(\d+)/) ){
digit = RegExp.$1.length;
}

for(var i = 1; i < sel.length; i++){
sel[i].contents = (num_to - unit * i).toFixed(digit);
}

Jun 18, 2009

Generate Handles

Here is a script which generates handles suitably for each selected pathes. Generated handles are extended at right angle to the line connecting the anchor and the center of the path.


Notes about anchor-points / handles in Illustrator scripting:
  1. A path is called "PathItem" in the script. And an anchor point is called "PathPoint". Every PathPoint has its own index number. It depends on the point which started drawing. Even the shapes drawn with the tools other than Pen tool have the order of PathPoints.
  2. Handles are called "rightDirection" and "leftDirection" in the script. And "right" and "left" don't mean the actual direction of them. It just depends on the direction of drawing.

It would be better if it had a preview. But you can adjust the length of the handles by selecting segments and resizing it. Here is an example of the operation.

video

download: b_aics_script_generate_handles.zip

Jun 13, 2009

Selected Status of Anchor Points

With Illustrator's scripting function, you can examine the selected state of any anchor point (PathPoint), and let a script affect only for anchors which are in particular state.

The available values are:
  • ANCHORPOINT
  • LEFTDIRECTION
  • LEFTRIGHTPOINT
  • NOSELECTION
  • RIGHTDIRECTION
With the following script, you can check the state that each anchor point is in.
// shows selected state of each anchor of the selected path
var pi = activeDocument.selection[0];
var p = pi.pathPoints;

for(var i = 0; i < p.length; i++){
alert( p[i].selected );
}
The following another simple script selects every other anchor of the selected pathes.
(Grouped pathes and compound pathes are ignored.)
// selects every other anchor of the selected pathes.
var sel = activeDocument.selection;

var p, i;
for(var j = 0; j < sel.length; j++){
sel[j].selected = false;
p = sel[j].pathPoints;

for(var i = 0; i < p.length; i++){
if( i % 2 == 1 )
p[i].selected = PathPointSelection.ANCHORPOINT;
}
}
After running this script, you can apply the effect of tools only to the selected anchors.

Jun 9, 2009

image: Circles on Sphere

This is an image generated by Illustrator script.

Basically, the method is simple. It is to draw an ellipse, then rotate it around the center of the large circle. This is not an accurate expression of 3D object. But I think it can not be a problem for the purpose of this case.

Light colored shapes mean that they are on the back side of the sphere.
At first, it seemed that they're sligntly unnatural in size, so I added perspective factor to the size of the ellipses.

download: b_aics_script_circles_on_sphere.zip

Jun 7, 2009

Drawing a Dot With 2 Anchors

I often draw a dot with 2 anchors.
To draw this, drawing a horizontal line and set the width of it to zero, then set the stroke cap type to the Round Cap.


This method enables to seve the number of anchors as compared with drawing a circle with 4 anchors.
Additionally, if you set Resize tool's option to keep the stroke width, you can adjust the density of dots without scaling each of them.

To use the dot, I usually drag it into Brush palette, and register as a scatter brush.
Then I drag on the artboard.


... Looks dirty. Let's clean it by removing the overlapped dots with a script.


Now looks OK.

Before using the following script, you must expand the brush and then ungroup it so that every item is appeared as <Path> in the Layers palette. (You may have to ungroup twice after expand it.)
Then remove useless path (the track of the brush).

If I write a script for general purpose, I'll automate this ungroup process, and insert the error handling to avoid baffling abending.
But this time, I wrote this for one-time use and for my own use.
I often write small scripts like this to automate the boring part of daily work.

// removes overlapped dots
var sel = activeDocument.selection;
var j;
var vb = sel[0].visibleBounds;
var w = vb[2] - vb[0]; // right - left
w *= 1.25; // adds margin
w *= w; // for comparison of squared distance

for(var i = sel.length - 1; i > 0; i--){
for(j = i - 1; j >= 0; j--){
if( dist2(sel[i].pathPoints[0].anchor,
sel[j].pathPoints[0].anchor) <= w ){
sel[i].remove();
break;
}
}
}
// -------
function dist2(p, q){
return Math.pow(p[1] - q[1], 2)
+ Math.pow(p[0] - q[0], 2);
}

Jun 5, 2009

Round Corners Issue

When drawing a circle with 4 points by bezier curve, the ratio of the handle length to the radius is about 0.5522847 (4 * (sqrt(2) - 1) / 3).

I thought Illustrator's "Round corners" filter (and effect) uses this ratio for the specified "radius". But I was wrong.

I measured length of the handles with a script (at end).
Maybe it uses more simple rule -- multiplying 0.55 by the radius.
Though it may not become a problem most of the time.

Anyway, it uses fixed length of handle for any corner. The corners are rounded, but they are not the arcs of specified radius most of the time.
Is it an useless low-quality tool? At least, it isn't always bad.
Applying it to the slanted rectangle like below, the effect may be as expected.
What if it strictly uses arcs in this case?
Though it is sure that it would be nice if we had that tool.

My script "Round Any Corner" (placed in my alternate site) basically uses same algorithm as above (but the ratio is 0.5522847). Because I think this method creates a neat shape that is suited for design, rather than using arcs. And to be honest, rounding the intersection point of curves by arc is difficult to script for me. Awfully troublesome at least.

It doesn't always creates arcs, and (unfortunately) isn't intended for that purpose.

// measures length of the handles
const FONT_SIZE = 9;
const FONT_NAME = "TimesNewRomanPSMT";
const DIGIT = 4;

var pi = app.activeDocument.selection[0];
var p = pi.pathPoints;
var d;

for( var i = 0; i < p.length; i++ ){
d = dist(p[i].anchor, p[i].rightDirection);
if(d > 0)
drawText( d.toFixed( DIGIT ), p[i].rightDirection);

d = dist(p[i].anchor, p[i].leftDirection);
if(d > 0)
drawText( d.toFixed( DIGIT ), p[i].leftDirection);
}
// -------
function drawText(txt, pos){
with(activeDocument.activeLayer.textFrames.add()){
contents = txt;
with(textRange){
with(characterAttributes){
size = FONT_SIZE;
textFont = textFonts.getByName( FONT_NAME );
}
with(paragraphAttributes){
justification = Justification.CENTER;
}
}
position = [pos[0] - width / 2, pos[1] + height / 2];
}
}
// -------
function dist(p, q){
return Math.sqrt(Math.pow(p[1] - q[1], 2)
+ Math.pow(p[0] - q[0], 2));
}

Jun 1, 2009

Ultra Fast Way to Draw Primitive Solids

... with Adobe Illustrator.


Cylinder
  1. Select the bottom anchor, and press Ctrl-X.
  2. Press Ctrl-F, and drag it downward with Shift key pressed.
  3. Select the right side anchors and press Ctrl-J. Do the same for the left side.
  4. Press Ctrl-F again.

Box
  1. Draw a rectangle.
  2. Drag the right side segment. Then select whole shape and press Ctrl-C.
    Then press Ctrl-F twice.
  3. Drag the left side segment.
  4. Drag the lower side segment.
  5. Select marked anchors, then drag one anchor to be snapped.
  6. Colorize as you prefer.

Cone
  1. Draw an oval.
  2. Drag with Alt key pressed to duplicate. Snap the lower anchor to the center.
  3. Drag the upper box of the bounding box with Shift key pressed, so that the shape is enlarged with keeping the aspect ratio.
  4. Draw a path with Pen tool to connect the intersection points and the upper anchor.
    -- These 2 lines are exactly tangential to the oval. (To be accurate, these are almost tangential because the oval is an approximated one by the bezier curve.)
  5. Unite with pathfinder if it needs.

May 31, 2009

Working With Symbols

The available scripting operations for symbol item are almost despairingly limited in AI CS3. As follows.

symbol properties -- name, parent, typename
symbol methods -- duplicate, remove

You can not even get coordinates of it directly.

One solution is to put a symbol into a group manually, and then you can manipulate the symbol through the group.

Suppose there's a grouped symbol on the artboard, like this.


Then you can get this image by running the following script.


// ----------------------------------------------
// places groups along a circle
const RADIUS = 120;
const DIV = 12;

with(app.activeDocument){
var gr = activeLayer.groupItems[0];
var radian = Math.PI * 2 / DIV;

for(var i = 0; i < DIV; i++){
with(gr.duplicate()){
translate( RADIUS * Math.cos(i * radian),
RADIUS * Math.sin(i * radian) );
}
}
}
// ----------------------------------------------

May 30, 2009

What Is This?

I have a website mainly for placing scripts for graphics softwares. And sometimes I receive e-mails of questions, requests and proposals about them. I thought it would be better off sharing some contents in these messages which I wrote. That's why I created this blog page. (This doesn't mean that I'll post other person's message without permission.)

I'm Japanese and I think I need to study English. Writing something may be worth doing for me.