Neatly fitting a dash to a rect

2013-12-12 Thread Graham Cox
Does anyone have code or at least an outline of how to adjust a dash so that it 
fits exactly to the corners of a rectangle?

The dash itself is supplied, but may be minimally adjusted in both phase and 
length of any of its elements to fit, such that the rect corners lie exactly in 
the centre of a solid part of the dash. It only needs to work for rects.


—Graham



___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Neatly fitting a dash to a rect

2013-12-12 Thread Andy Lee
I assume you mean dash as in NSBezierPath's setLineDash:count:phase:.  Also, 
does the dash have just two elements (one segment and one gap), or is it more 
complex.

Does it have to be the same exact pattern all the way around?  If it's okay to 
differ a teeny bit (I bet imperceptibly), you could solve the problem 
separately for the horizontal edges and the vertical edges, and draw four lines 
instead of one rect.

Offhand, here's what comes to mind, just solving for one edge and assuming the 
pattern is simply { segmentLength, gapLength }.

In the final solution, how many iterations of the pattern will the line have?  
If both ends are in the middle of a segment, the answer is the same as if one 
end were at the beginning of a segment and the other at the end of a gap.  In 
other words, the line length will be an exact multiple of segment length.

How far off are we from that?  Let's figure out how many iterations fit now, 
and how much is left over.  (Excuse my sloppy floating point coding.)

CGFloat iterationLength = segmentLength + gapLength;
CGFloat numIterations = floor(lineLength / iterationLength);
CGFloat leftOver = lineLength - (numIterations * iterationLength);

We want to spread the leftover amount evenly across all iterations, so let's 
figure out how much to add to each iteration.  We could split that fudge factor 
equally between the segment and the gap, and I bet no one would notice, or to 
be fussy we could distribute it proportionally:

CGFloat iterationFudge = leftOver / numIterations;  // Assume numIterations > 0.
CGFloat segmentFudge = iterationFudge * (segmentLength / iterationLength);
CGFloat gapFudge = iterationFudge * (gapLength / iterationLength);

CGFloat myDashPattern[2] = { segmentLength + segmentFudge, gapLength + gapFudge 
};

// Assume myBezierPath contains the line.
[myBezierPath setLineDash:myDashPattern
count:2
phase:(myDashPattern[0] / 2.0)];

You could probably tweak some things to minimize rounding issues, but I don't 
know if that would make a noticeable difference.

--Andy

On Dec 12, 2013, at 7:54 AM, Graham Cox  wrote:

> Does anyone have code or at least an outline of how to adjust a dash so that 
> it fits exactly to the corners of a rectangle?
> 
> The dash itself is supplied, but may be minimally adjusted in both phase and 
> length of any of its elements to fit, such that the rect corners lie exactly 
> in the centre of a solid part of the dash. It only needs to work for rects.
> 
> 
> —Graham



___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Neatly fitting a dash to a rect

2013-12-12 Thread Andy Lee
On Dec 12, 2013, at 10:06 AM, Andy Lee  wrote:
> Does it have to be the same exact pattern all the way around?  If it's okay 
> to differ a teeny bit (I bet imperceptibly), you could solve the problem 
> separately for the horizontal edges and the vertical edges, and draw four 
> lines instead of one rect.

Not sure if this might come out looking wrong depending on lineCap/lineJoin 
styles.

If so, all I can think of is to figure out *two* sets of "fudge" amounts, for 
the horizontal and vertical edges, and maybe apply their average to the dash 
pattern.  I don't know if the math would work out.  This is already just about 
as much as my brain can handle at the moment. :)

--Andy



___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Neatly fitting a dash to a rect

2013-12-12 Thread Andy Lee
On Dec 12, 2013, at 10:06 AM, Andy Lee  wrote:
> In other words, the line length will be an exact multiple of segment length.

Correction: exact multiple of (segmentLength + gapLength).

--Andy


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Neatly fitting a dash to a rect

2013-12-12 Thread Graham Cox

On 12 Dec 2013, at 4:06 pm, Andy Lee  wrote:

> I assume you mean dash as in NSBezierPath's setLineDash:count:phase:.

Yep, sorry if that wasn’t clear.

>  Also, does the dash have just two elements (one segment and one gap), or is 
> it more complex.

Well, it can be more complex, but it might not matter. The remainder of the 
dash after the first ‘solid’ part can probably be considered as ‘gap’ for the 
purposes of this. Most of the time it will be a simple dash.

> Does it have to be the same exact pattern all the way around?  If it's okay 
> to differ a teeny bit (I bet imperceptibly), you could solve the problem 
> separately for the horizontal edges and the vertical edges, and draw four 
> lines instead of one rect.

It doesn’t *have* to be the same as long as it doesn’t differ too much 
visually, but detecting that a path is a simple rect (including rotated cases) 
and breaking it into h and v lengths might turn out to be the hard part. I also 
wonder if there’s a way to perform the calculation based on the highest common 
factor (HCF) of the horizontal and vertical edges? That might allow the dash to 
be tweaked as a single entity and applied in the usual way.


> Offhand, here's what comes to mind, just solving for one edge and assuming 
> the pattern is simply { segmentLength, gapLength }.

I’ll experiment with this and see where it takes me, thanks :)

—Graham



___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Neatly fitting a dash to a rect

2013-12-12 Thread Andy Lee
On Dec 12, 2013, at 10:52 AM, Graham Cox  wrote:
>> Does it have to be the same exact pattern all the way around?  If it's okay 
>> to differ a teeny bit (I bet imperceptibly), you could solve the problem 
>> separately for the horizontal edges and the vertical edges, and draw four 
>> lines instead of one rect.
> 
> It doesn’t *have* to be the same as long as it doesn’t differ too much 
> visually, but detecting that a path is a simple rect (including rotated 
> cases) and breaking it into h and v lengths might turn out to be the hard 
> part. I also wonder if there’s a way to perform the calculation based on the 
> highest common factor (HCF) of the horizontal and vertical edges? That might 
> allow the dash to be tweaked as a single entity and applied in the usual way.

Interesting.  You could straighten out the angles of the rect and think of 
(say) the top and right edges as a single line:

o---+---+---+---+---o---+---+---o

Each of o's is a corner, and each of the +'s marks off a multiple of the HCF.  
So what you want is for the dash to be tweaked in such a way that all three o's 
are in the middle of some segment.

Sounds fun -- good luck!

--Andy


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com