-
Notifications
You must be signed in to change notification settings - Fork 94
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement hatch
entity
#36
Comments
Hello, |
My first suggestion of approach is using I found that there is a Custom Shader Material third party. I'm not sure this helps us or not, but at least there is a chance to be so. This might helps us define custom textures.
Still more research is required for other possibilities. For example, more procedural options (see this) might be computational challenging. But I think these kind of hatching is less urgent than predefined things. I'm not sure whether it it possible or desirable to implement 100% spec-covering, since this library doesn't seem to aim for making a general CAD editor. For such thing, we need to discuss the direction of developments. |
Thank you for your detailed explanation. I want to provide some of my thoughts with respect to your observations and other references:
What I have to do is just find some interval(s) in [0, 1], for each interval I, f(I) is in P. For the simplicity, Let's fix f is restricted to a single straight line, at least for right now. (scaling up is trivial, and within my comprehension, every Computing strategy to find such intersecting point should be differ to the property of P. P can be split into segments differently with boundary path type flag and edge type.
If there are N lines for f and M segments for p, then exactly NM solving process is required. I don't have further optimization idea for just right now to drop this complexity. |
Simple Algorithm Showcase for Polyline
|
OK, this might work. |
pretty brilliant!
I thought this might be hard but it wasn't. It was trivial than I expected. Whether polylines are nested or not doesn't affect to the algorithm. All I have to do is just count the intersections and determine the start point is interior. Note that degenerate cases are ambiguous whether it's truley outside or inside. Nevertheless it works fine with even-odd rule, by not letting adjacent surfaces being not both inside or outside. https://editor.p5js.org/Phryxia/sketches/LleM_jJ1h But still there is buggy behavior as you can see above- edge case for the vertex. If line crosses path's vertex (or intersection of two path for degenerate cases) exactly, it is counted as twice currently. This screws up entire even-odd rule. To handle this I should think about handling near vertex case. |
After few tweaking, I realize that hazard one is vertex-case only. Degenerate or wrapping path doesn't matter since it can be thought of separated area. And vertex case can be detected easily, because solving linear equation of two line return two interpolation value This logic is applied to above demo link |
That's interesting findings. What if you would account intersection with line only in range |
This is why I love to cooperate for ideation. You're right, I confirmed that such approach is theoretically and practically works perfectly, and it's performance-healthy as duplication check is not required. |
And the last small detail: Defining area (or positions) to generate pattern is just bounding box of given geometry, which can be obtained within O(n) time complexity, for n boundary path length. |
OK, looks like things are getting serious, so there is no way back anymore :) Let's plan the work. First, we should define the limited scope.
Overall milestones to do in dxf-viewer code and architecture design:
Actual tasks for current stage:
I have created |
Seems to be a long journey. As I haven't inspect the entire code base, few parts of your explanation seems unclear for right now but by proceeding from small implementation I think I can get there soon. First I'll proceed to implement parser. And here a very simple hatch example generated by qcad. This has seven hatchs defined by external. (QCAD can only create a hatch by external as my understanding) Top left one is polyline. More complex example (more than 1 depth nesting, varied edge types...) has to be done manually. Note that line-looking one with right bottom one is degenerate case. Image is rendered by reference viewer. By the way, do you have any plan to introduce typescript to this repo? If you're busy, I can help you that first. This will help everyone develop more easily, with rich support for IDE and more safe code behavior. I have experienced (for example) handling lots of configuration file related to repository. (Note that I'm actually the author of that, but for some private reason I'm using coworker's account) |
Yes, it is in my todo list indeed. It looks quite trivial to migrate the core code to it. However, I had a plan to significantly rewrite the parser simultanenously with this migration. Introducing strong typing into its current implementation (which is forked 3rd-party component) seems is not straight forward. Also it would be nice to change overall approach used in the parser, to make it true streaming parser. Currently it loads all the DXF text content fully in the memory as a single string, which limits the possible DXF size to ~1GB, then browser JS string size limit is reached. Also memory consumption equal to file size is not necessary. I have DXF sample which has big embedded OLE object, which we could easily ignore and display the rest content, but it cannot be loaded due to this unnecessary bufferring. If you want, I can start this migration before proceeding with hatching implementation. However, I do not see real possibility to parallel this work. Describing all the types in DXF viewer is a task for me, since I am the only person knowing this in details. Some advices on configuration and overall layout might be welcome indeed. If we proceed with this way, I would advice you to continue on hatching task, since it can be effectively paralleled. Having full implementation of BTW |
Oh I see. I think it's very important issue. So let's make typescript to wait for refactoring.
Since I have some deadline for my contraction, it's hard to wait until the migration. I'm also pessimiste to parallel work- especially current commit policy: squash merge. Note that sqaush and even rebase merge, conflicts a lot. (Not rebasing my branch but it matters when merging PR on github) This is because git's conflict detection is based on finding common ancestor and compare them, and squash & rebase merge has only one parent. It's a matter of preference, but obviously parallel working and squashing often fight each other as my experience at company's works. Therefore, I think implementing hatch ASAP seems to be better option.
I definetely agree. I've used |
OK, let's postpone TypeScript and focus on hatching now. I still propose you to get |
Actually conflicts occurs independently from using or not using rebase, if the same place is changed simultaneously in different branches, you will get conflict anyway. You can use any merge policy you want, I can handle the final reintegration to master branch to make the history linear. Just need to ensure that our changes are based on the same branch ( |
Oh, that's the priority. I'll go for it~ Can I introduce jest with above also? And by the way, few hours before I sketched following parser structure so that I can get some meaningful data. (The time that I haven't thought about separating // declarative schema for each
const Schema = [
{
// Subclass marker (=AcDbHatch)
code: 100,
name: 'subclassMarker',
parse: (value, scanner) => value // value parma should be injected from scanner.next().value
},
// Elevation point (in OCS)
{
code: 10,
name: 'elevationPoint',
parse: (value, scanner) => helpers.parsePoint(scanner)
},
// Extrusion direction (optional)
{
code: 210,
name: 'extrusionDirection',
parse: (value, scanner) => helpers.parsePoint(scanner),
fallback: { // for optional field,
x: 0,
y: 0,
z: 1,
}
},
// ...
}
// common logic (pseudocode)
let sptr = 0
let curr = scanner.next()
while not eof:
const schema = Schema[sptr++]
const entity = {}
if schema.code ≠ curr.code:
if !schema.fallback: throw error
entity[schema.name] = fallback
continue
entity[schema.name] = schema.parse(curr.value, scanner)
curr = scanner.next() |
Sure. It would be nice to start some movement to this direction.
Declarative approach is a way to go, indeed. I will consider something similar when will make a rewrite of a parser. However, currently it may be better to follow existing code look-and-fill. Another quick notes on your code - it assumes some specific groups order, I am not sure if it is always the case for real-world files. I did not find this requirement in DXF specification, it may be asserted for some sequences like |
Thanks I'll do it.
I even found saying DO NOT rely on order that here. Therefore you're right. But I wonder the case of undeterminable case like
Just forget about this- I misunderstood the specification group code.
Yeah, if you worries about redundant memories to hold such field, they must be commented out. so I think current implementation may parse correctly with few modification. (Though I haven't inspect all entities, and also I don't have sense to detect which I should ignore or not) Anyway for
And I'll just concentrate on calculator, at least for now. (and jest) |
Did you get, what does this "seed point" mean? Why there can be multiple seed points specified? I did not find any information on that, my current assumption is that it defines hatch pattern instantiation origin coordinate. And multiple of them means that the pattern can be instantiated multiple times in one Just for fun I have asked ChatGPT about that, and it answered exactly the same as I assumed, however you might know that information it provides is not yet considered to be reliable, and it does not provide any source references for that. ChatGPT_dxf_hatch_seed_points.pdf And yes, this is exactly the case, when subclass markers should be considered and should affect current parsing context. For now, it is quite trivially to remember last subclass encountered and interpret group |
I think I found the right one... but I can't understand what is exactly means as I'm not expert on using CAD... Can you explain to me this docs more easier? https://help.autodesk.com/view/ASMECH/2016/ENU/?guid=GUID-1C7B56A1-D396-4A28-9A6F-51C07438B46E |
Ingredient for hatch rendering
Ingredient for hatch rendering
Ingredient for hatch rendering
Seems this doc is not related to hatch seed points, looks like completely different topic. But I think my assumptions described in my previous message look believable enough, just need to check them by making a sample file. |
I have implemented basic parsing for HATCH entity. I did not finish spline boundary type parsing, will do it later. I noticed that QCAD always creates pattern as pre-defined, referencing it by name, even for completely custom patterns like QCAD logo. It defines simple line as a fallback, so it is always displayed as simple line hatch in the reference viewer. Also was unable to find example files with custom pattern. Probably will need to somehow synthesise one. Actually this also is valid for most of other hatch features. By the way, if the solid fill will be supported in the future, seems the current approach will need to be redesigned. Solid infill will need polygon definition (probably in form of polygon with holes structure). Thus the algorithm will need to generate such polygons. Then it will probably be more efficient to clip the pattern lines by these polygons. |
Once it is done and proved to be working, one can write a paper about this method and make it academic 😁 |
I have seen some mentions about |
According to AutoCAD docs (1, 2, 3), I was pretty close to the truth. Patterns in BTW just implemented dashes support. Hatch clipping seems to be complete. |
Here are pat files in QCAD project. |
…tch entity. Some builtin patterns added.
Almost finished the initial roadmap for this feature. Just added spline support. One more fun fact: QCAD is not able to display spline hatch it produces. The only thing I currently see which stops merging this feature in master is suspicious behaviour on this file: Autodesk: |
The problem was in bulged polyline segments handling, fixed. So after implementation of proper handling for metric/imperial patterns this feature can be released, if no more problems found. |
Just have finished separate patterns for imperial and metric. Everything is looking good now. The feature is merged into master and will be included in the nearest release (currently blocked by #51). |
This is awesome work! Last time I checked, even Autodesk Forge Viewer rendered hatches serverside and transfered them as disconnected line segments, which usually resulted in hatches being a huge part of their .f2d files. |
Hello, I'd like to implement the parser and renderer for
hatch
entity. Since this feature is essential to the CAD user, IMO it's important and valuable to proceed. My final goal is implementing a rendering logic for hatch, but to do so I have to parsehatch
entity first.If someone has any plan to do so (or even currently doing it), let's talk about more so that I can help and elaborate. If it's not, may I proceed to implement such feature? @vagran
Milestones
TBD
Reference
The text was updated successfully, but these errors were encountered: