Break Line
When having layouts that includes very long parts of models, typically break lines are best. In the app below break lines are added when the pipe length is over 50 mm so that it doesn't overflow the visualization, but keeping the dimension updated with a fixed size.
There are many approaches on how to do this depending on the case, and even different styles that you as the developer can implement. For the case of the pipe we follow these steps so you understand all the factors involced in a cropped layout with a break line:
1. Identify Layout​
When you are cropping a layout or sketch, make sure to isolate it as much as possible. It's best to crop just what you need rather than crop a whole layout and adjust it later with additional rows of code. For the case of the pipe system above, we want to crop somehow the straight horizontal pipe so that the user has a better view of the whole pipe system without the need of zooming in or making the dimension texts larger.
2. Crop​
Depending on the elements you have there might be better and more suitable approaches. Perhaps using a static sketch might be more handy than making boolean operations to layouts or sketches. So if you want to crop a:
-
SKYCAD.Sketch: recommended when you just want to crop a single sketch, either create a custom sketch just for the sole purpose of showing it as cropped, or use any of the available boolean operations. Perhaps cut a sketch with another sketch with a custom shape or a simple rectangle might do the work more than nicely.
-
SKYCAD.Layout: recommended when you want to crop a layout with multiple sketches, dimensions and texts, then it's best to use layout.crop().
For the case of the pipe system, we will perform two layout.crop()
so that we get both parts (orange areas in picture
below). Also for this particular case we want not to crop when the pipe is too short. We will put the limit at 50 mm for
this case (see pipeLengthLimit
in code snippet below).
See that we want to get rid of the dimension or texts when using
layout.crop()
since we want to add a static one with dynamic text. For this you can uselayoutToCrop.crop(cropBounds, { keepDimensions: false, keepTexts: false })
.
So in the snippet below we present a first possible solution where we just crop both parts but we don't adjust their
positions yet. We say that the cropped part should be 20 mm (see cropWidth
).
const layout = new SKYCAD.Layout({ defaultDimensionContinuousLines: true })
const horizontalPipeLayout = GEOM2D.generatePipeStraightLayout(pipeLength) // includes dimension
const pipeLengthLimit = 50
const cropWidth = 20
if (pipeLength > pipeLengthLimit) {
// Left crop
const leftCropLayout = horizontalPipeLayout.clone()
const leftBounds = new SKYCAD.Bounds2D(
new SKYMATH.Vector2D(0, -0.5 * PIPE_DIAMETER - JOINT_OVERHANG - 20),
new SKYMATH.Vector2D(cropWidth, 0.5 * PIPE_DIAMETER + JOINT_OVERHANG + 20),
)
leftCropLayout.crop(leftBounds, { keepDimensions: false })
layout.addLayout(leftCropLayout, {
position: new SKYMATH.Vector2D(25, 25),
})
// Right crop
const rightCropLayout = horizontalPipeLayout.clone()
const rightBounds = new SKYCAD.Bounds2D(
new SKYMATH.Vector2D(pipeLength - cropWidth, -0.5 * PIPE_DIAMETER - JOINT_OVERHANG - 20),
new SKYMATH.Vector2D(pipeLength, 0.5 * PIPE_DIAMETER + JOINT_OVERHANG + 20),
)
rightCropLayout.crop(rightBounds, { keepDimensions: false })
layout.addLayout(rightCropLayout, {
position: new SKYMATH.Vector2D(75, 25),
})
} else {
layout.addLayout(horizontalPipeLayout, {
position: new SKYMATH.Vector2D(25, 25),
})
}
3. Adjust Position​
Now the next step would be to adjust the position of both parts so they remain in the same dimension as they would look
for pipeLength = 50
for example.
Then we will replace cropWidth
with breakLineWidth
that will determine the space that we want to leave between and
adjust both cropped layouts bounds and positions accordingly cropped layouts.
const horizontalPipeLayout = GEOM2D.generatePipeStraightLayout(pipeLength)
const pipeLengthLimit = 50
const breakLineWidth = 15
if (pipeLength > pipeLengthLimit) {
// Left crop
const leftCropLayout = horizontalPipeLayout.clone()
const leftBounds = new SKYCAD.Bounds2D(
new SKYMATH.Vector2D(0, -0.5 * PIPE_DIAMETER - JOINT_OVERHANG - 20),
new SKYMATH.Vector2D(0.5 * (pipeLengthLimit - breakLineWidth), 0.5 * PIPE_DIAMETER + JOINT_OVERHANG + 20),
)
leftCropLayout.crop(leftBounds, { keepDimensions: false })
layout.addLayout(leftCropLayout, {
position: new SKYMATH.Vector2D(25, 25),
})
// Right crop
const rightCropLayout = horizontalPipeLayout.clone()
const rightBounds = new SKYCAD.Bounds2D(
new SKYMATH.Vector2D(
pipeLength - 0.5 * (pipeLengthLimit - breakLineWidth),
-0.5 * PIPE_DIAMETER - JOINT_OVERHANG - 20,
),
new SKYMATH.Vector2D(pipeLength, 0.5 * PIPE_DIAMETER + JOINT_OVERHANG + 20),
)
rightCropLayout.crop(rightBounds, { keepDimensions: false })
layout.addLayout(rightCropLayout, {
position: new SKYMATH.Vector2D(-pipeLength + 75, 25),
})
} else {
layout.addLayout(horizontalPipeLayout, {
position: new SKYMATH.Vector2D(25, 25),
})
}
4. Restore Annotations​
Now it's time to "restore" dimensions and texts we have removed. If their position depend on pipeLength
remember to
swap this dependency with the capped property (i.e pipeLengthLimit
here).
In this case make sure to use the argument text
of the dimension and add the actual length pipeLength
there. See
that both nodes of the dimension are static and do not depend on pipeLength
at all.
if (pipeLength > pipeLengthLimit) {
// Left crop
// Right crop
// Dimension
layout.addDimension(new SKYMATH.Vector2D(25, 35), new SKYMATH.Vector2D(25 + pipeLengthLimit, 35), {
text: `${pipeLength}`,
offset: 10 + 0.5 * PIPE_DIAMETER,
textSize: 5,
extendLinesToTarget: true,
})
} else {
// original layout
}
5. Break line​
And finally it's time to "fill" the gap with elements that the user can identify the layout as "cut". You can have
different styles, create your own static sketches and scale them accordingly (perhaps dependent on PIPE_DIAMETER
here). Depending on the shape and even material sometimes the break line must have different shapes. E.g. in cylinders a
"drop-shaped" sketch is to be used (see picture below).
For now, we will simply do the typical break lines as shown below:
In this case we will add two lines both at the center of the pipe but separated by breakLineWidth
in a function from
GEOM2D that could be called generateBreakLineLayout()
.
if (pipeLength > pipeLengthLimit) {
// Left crop
// Right crop
// Dimension
// Break line
layout.addLayout(GEOM2D.generateBreakLineLayout(breakLineWidth), {
position: new SKYMATH.Vector2D(25 + 0.5 * pipeLengthLimit, 25),
})
} else {
// original layout
}
// In GEOM2D
export function generateBreakLineLayout(breakLineWidth: number) {
const layout = new SKYCAD.Layout()
const lineSketch = new SKYCAD.Sketch()
lineSketch.moveTo(0, 0.5 * PIPE_DIAMETER + JOINT_OVERHANG)
lineSketch.lineTo(0, 2.5)
lineSketch.lineTo(2.5, 1)
lineSketch.lineTo(-2.5, -1.5)
lineSketch.lineTo(0, -2.5)
lineSketch.lineTo(0, -0.5 * PIPE_DIAMETER - JOINT_OVERHANG)
layout.addSketch(lineSketch, {
position: new SKYMATH.Vector2D(-0.5 * breakLineWidth, 0),
})
layout.addSketch(lineSketch, {
position: new SKYMATH.Vector2D(0.5 * breakLineWidth, 0),
})
return layout
}
A good and simple alternative to fake custom shape cropped bounds would be to add a filled sketch in white within both lines so that it's shown as it follows the shape of the break line in the case you have lines from the original sketch going into the break line somehow. It's up to you how much detail and simplicity you want to add to your break lines!